Connecting to an embedded device Using paramiko and pyyaml #2

The second and last part containing the two sections of connecting to embedded device will be seen here. I am going to get the support of yaml to store the commands.

Before going into how we are going to do it, lets see a bit about what yaml is.

yaml or YAML Ain’t Markup Language 🙂 is a human friendly data serialization standard. It has APIs in all programming languages and we are going to use the python version of yaml called the PyYaml.

In my words using pyyaml we are going to store the set of commands and their expected output in a human readable format. We will see how.

PyYaml has a specific format for storage of the information. We are going to make use of the nesting facility in yaml syntax to nest both a command and its subsequent result together. To learn more about pyyaml and its syntax please visit http://pyyaml.org/wiki/PyYAMLDocumentation.

The file is stored as command.yaml and contains information like below.

- command: command_to_be_exec
  result: result_of_cmd
- command: second_cmd
  result: res_of_sec_cmd

The above format actually corresponds to Python dictionary format where “command” is key and “command_to_be_exec” is the value. This recognition will be important as it will be useful when you look at the parsed output. so using pyyaml we are going to parse and get the commands in pythonic format for easy execution.

import yaml
conts = yaml.load(open("text.yaml"))

We parse the contents given above using the load method in pyyaml. The method loads and generates a list of dictionaries where the command to be executed will be value and the “command” word will be key. Exactly as given in the yaml file.

print conts
[{'command': 'command_to_be_exec', 'result': 'result_of_cmd'}, {'command': 'second_cmd', 'result': 'res_of_sec_cmd'}]

Now it will be easy to create a small python module to combine both.

import devconnect

def parse_yaml(yaml_file):
    """
    Method to parse the yaml file provided and give the contents in pythonic format.
    :param yaml_file: yaml file to be parsed
    :return: contents of the file
    """
    conts = yaml.load(open(yaml_file))
    return conts

def executeCommands(hostname, username, password):
    """
    Method to execute the commands in yaml by integrating with the devconnect
    file and creating a object for DevConnect class.
    """
    cmdfile = "commands.yaml"
    dcon = devconnect.DevConnect(hostname, username, password)
    data = parse_yaml(cmdfile)
    for test_no, cmd in enumerate(data):
        print "Executing test number: %d and command: %s" % (test_no+1, cmd["command"])
        rc, out, err = dcon.runCommand(cmd["command"])
        print "out"

Now the above code just prints the output executed in the device. But you guys can use these modules in more efficient way and create an entire test suite for the device.

That’s all folks. Please dont forget to like my posts if its good and informative. And dont forget to look into the documentation of paramiko and pyyaml. I have provided them in the references.

References:

http://docs.paramiko.org
http://pyyaml.org/wiki/PyYAMLDocumentation

Connecting to an embedded device Using paramiko and pyyaml #1

Command execution is one of the important part to be automated in any devices like Switches, Routers or any other embedded device. Any specific task to be done in such embedded devices may result in running a set of commands. This may be a basic configuration or a specific feature configuration done in the device. It is best to automate this as it can reduce the effort of the tester.

Lets see a common way of doing this. I am going to take the help of paramiko and pyyaml to do the same.

So we are going to see this in three sections. They are,

  1. Section which talks about connecting to the embedded device with paramiko
  2. Section which talks about the parsing the pyyaml
  3. Section which talks in integrating both to get results

Lets see the first part here.

paramiko enables us to connect to the device through a secure SSH channel. The module enables us to create a SSH Channel, SSH client, Transport etc. To learn more about the module please visit http://docs.paramiko.org/

They have explained the API well in the above link.

Here we are going to see just a way to connect to device using this package.

So first of all we are deciding to create a class for the same. This is because we dont want to make it functional and call the device each and every time for each command to be executed. So how are we going to use paramiko to connect to a device?

First start with the import of the module

import paramiko

paramiko has a class with which we can connect to a particular host and port with a username and password provided for authentication. This class is SSHClient. We need to create an object and use connect() method to connect to the device.

dev_client = paramiko.SSHClient()
dev_client.connect("krishnan.device.com", "user1", "password1")

Now dev_client has connected to the device with hostname “krishnan.device.com” authenticated with credentials “user1” and “password1”. Now we can use the client to execute commands in the device and return the output. This can be done using the exec_command() method in SSHClient Class.

rc, output, error = dev_client.exec_command("command_to_execute")

This method returns the stdin, stdout and stderr as 3 tuple. We can grep the rc for command execution status. If pass we can check the output variable for output and if fail check the error variable for error.

We can even create an interactive shell session for executing string of commands using it. This is done by the method invoke_Shell(). It opens a new channel connected to a pseudo terminal.

Now lets see how to put things together in a class.

__author__ = 'Krishnan'

import paramiko
from paramiko.ssh_exception import SSHException

class DevConnectException(Exception):
    pass

class DevConnect(object):
    """
    This Class is uses Paramiko module to create a SSH Connection to
    the Device under test named. The DUT can be contacted through
    commands remotely from a server by opening a secure shell connection
    through this class
    """
    def __init__(self, host, uname, passwd):
        """
        Object initialisation
        :param host: Hostname of the DUT
        :param uname: Username of the DUT
        :param passwd: Password of the DUT
        :return:
        """
        self.host = host
        self.uname = uname
        self.passwd = passwd
        self.devclient = paramiko.SSHClient()
        self.devclient.connect(host, uname, passwd)

    def createChannel(self):
        """
        This method will be used to create a interactive connection
        between the Device under test and server for sending commands
        through SSH Connection.
        :return: The new SSH Channel created
        """
        try:
            self.devchannel = self.devclient.invoke_shell()
        except SSHException, err:
            raise DevConnectException("Unable to invoke the SSH Command shell")

    def runCommand(self, cmd):
        """
        This Method will be used to run a command in the Device under test
        and return the output produced. If the command fails then the
        RtConnectException is raised.
        :param cmd: The command to be executed
        :return: tuple of command RC, command output and command error if any
        """
        try:
            stdin, stdout, stderr = self.devclient.exec_command(cmd)
            return (stdin, stdout, stderr)
        except SSHException, err:
            raise DevConnectException("Execution of command '%s' failed" % cmd)

    def closeConnection(self):
        """
        This method will close the created SSH Connection
        :return: None
        """
        self.devclient.close()


References:

docs.paramiko.org