#!/usr/bin/python

###############################################################################
# Written by:           <NAME>
# Creation date:        24/03/2018
# Last modified date:   19/08/2018
# Version:              v1.3
###############################################################################


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Standard library modules
import netmiko
import json
import sys                      
import datetime
import time
import logging
import os
import re

from colorama import init, Fore, Style
from progressbar import *

# Local modules
import tools


# Logs on the working directory on the file named runner.log
logger = logging.getLogger('__name__')
hdlr = logging.FileHandler('runner.log')
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%d/%m/%Y %H:%M:%S')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)


# If connection times out, the script will continue to run.
# If authentication fails, the script will continue to run.
netmiko_ex_time = (netmiko.ssh_exception.NetMikoTimeoutException)
netmiko_ex_auth = (netmiko.ssh_exception.NetMikoAuthenticationException)


# If arguments not equal to 3 we get an error.
if len(sys.argv) != 3:
    print(Fore.RED + '>> Usage:', '"' + sys.argv[0].split('/')[-1], 'x.json x.txt"' + Style.RESET_ALL)
    exit()


with open(sys.argv[1]) as dev_file:
    if sys.argv[1].split('/')[-1] == 'netbox.json':
        tools.get_netbox_devices()
        netbox_json = sys.argv[1].split('/')[-1]
        with open(netbox_json, 'r') as devices_tmp:
            devices = json.load(devices_tmp)
    else:
        devices = json.load(dev_file)


with open(sys.argv[2]) as cmd_file:
    commands = cmd_file.readlines()


# Prompt for username and password
print(Fore.WHITE + '='*79 + Style.RESET_ALL)
username, password = tools.get_credentials()


# Progress Bar
widgets = ['\n',
           Percentage(), ' ', Bar(marker='#', left='[', right=']'),
           ' ', '[',SimpleProgress(),']',' ' '[', ETA(),']', '\n']

pbar = ProgressBar(widgets=widgets)

def main():
    # Script start timestamp and formatting
    start_timestamp = datetime.datetime.now()
    start_time = start_timestamp.strftime('%d/%m/%Y %H:%M:%S')

    for device in pbar(devices):
        device['username'] = username
        device['password'] = password
        try:
            print(Fore.WHITE + '='*79 + Style.RESET_ALL)
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(current_time, '- Connecting to device:', device['ip'])

            # SSH into each device from "x.json" (2nd argument).
            connection = netmiko.ConnectHandler(**device)

            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            #success_connected = (current_time, '- Successfully connected -', device['ip'])
            success_connected = (current_time, '- Connection to device successful:', device['ip'])
            success_connected_str = ' '.join(success_connected)
            print(success_connected_str)
            print('-'*79)

            # Log the successful connection on the working directory in runner.log
            # Parse out the datestamp
            regex = r'(\d+/\d+/\d+\s+\d+:\d+:\d+\s+-\s+)(.*)'
            m_conn = re.match(regex, success_connected_str)
            logger.info(m_conn.group(2))

            # Get device's "hostname" from netmiko, and "ip" from .json
            hostname = connection.base_prompt
            ip = (device['ip'])

            # Log "start" locally on the device.
            sysargv = ' '.join(sys.argv)
            connection.send_command('send log 6 "Begin script: {}"'.format(sysargv))
            
            # Send each command from "x.txt" to device (3rd argument).
            for command in commands:
                # If only whitespace in line do nothing and continue.
                if command in ['\n', '\r\n']:
                    pass
                else:
                    print('[{0}] [{1}] >> {2}'.format(hostname, ip, command) + '\n')
                    print(connection.send_command(command))
                    print('\n' + '-'*79)

            # Log "end" locally on the device.
            connection.send_command('send log 6 "End script: {}"'.format(sysargv))

            # Disconnect SSH session.
            connection.disconnect()

            # Log the successful configuration on the working directory in runner.log
            success_configured = ('Configuration to device successful:', device['ip'])
            success_configured_str = ' '.join(success_configured)
            logger.info(success_configured_str)


        except netmiko_ex_auth as ex_auth:
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(Fore.RED + current_time, '- Authentication error:', device['ip'] + Style.RESET_ALL)
            # Log the authentication error on the working directory in runner.log
            logger.warning(ex_auth)

        except netmiko_ex_time as ex_time:
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(Fore.RED + current_time, '- TCP/22 connectivity error:', device['ip'] + Style.RESET_ALL)
            # Log the TCP/22 connectivity error on the working directory in runner.log
            logger.warning(ex_time)


        # Script end timestamp and formatting
        end_timestamp = datetime.datetime.now()
        end_time = end_timestamp.strftime('%d/%m/%Y %H:%M:%S')

        # Script duration and formatting
        total_time = end_timestamp - start_timestamp
        total_time = str(total_time).split(".")[0]


        # SCRIPT STATISTICS
        print(Fore.WHITE + '='*79 + Style.RESET_ALL)
        print("+" + "-"*77 + "+")
        print("|" + " "*30 + "SCRIPT STATISTICS" +      " "*30 + "|")
        print("|" + "-"*77 + "|")
        print("| Script started:         ", start_time, " "*31 + "|")
        print("| Script ended:           ", end_time,   " "*31 + "|")
        print("| Script duration (h:m:s):", total_time, " "*43 + "|")
        print("+" + "-"*77 + "+")


if __name__ == "__main__":
    main()

#!/usr/bin/python

###############################################################################
# Written by:           <NAME>
# Creation date:        24/03/2018
# Last modified date:   19/08/2018
# Version:              v1.3
###############################################################################


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Standard library modules
import netmiko
import json
import sys                      
import datetime
import time
import logging
import os
import re

from colorama import init, Fore, Style
from progressbar import *

# Local modules
import tools


# Logs on the working directory on the file named runner.log
logger = logging.getLogger('__name__')
hdlr = logging.FileHandler('runner.log')
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%d/%m/%Y %H:%M:%S')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)


# If connection times out, the script will continue to run.
# If authentication fails, the script will continue to run.
netmiko_ex_time = (netmiko.ssh_exception.NetMikoTimeoutException)
netmiko_ex_auth = (netmiko.ssh_exception.NetMikoAuthenticationException)


# If arguments not equal to 3 we get an error.
if len(sys.argv) != 3:
    print(Fore.RED + '>> Usage:', '"' + sys.argv[0].split('/')[-1], 'x.json x.txt"' + Style.RESET_ALL)
    exit()


with open(sys.argv[1]) as dev_file:
    if sys.argv[1].split('/')[-1] == 'netbox.json':
        tools.get_netbox_devices()
        netbox_json = sys.argv[1].split('/')[-1]
        with open(netbox_json, 'r') as devices_tmp:
            devices = json.load(devices_tmp)
    else:
        devices = json.load(dev_file)


with open(sys.argv[2]) as cmd_file:
    commands = cmd_file.readlines()


# Prompt for username and password
print(Fore.WHITE + '='*79 + Style.RESET_ALL)
username, password = tools.get_credentials()


# Progress Bar
widgets = ['\n',
           Percentage(), ' ', Bar(marker='#', left='[', right=']'),
           ' ', '[',SimpleProgress(),']',' ' '[', ETA(),']', '\n']

pbar = ProgressBar(widgets=widgets)

def main():
    # Script start timestamp and formatting
    start_timestamp = datetime.datetime.now()
    start_time = start_timestamp.strftime('%d/%m/%Y %H:%M:%S')

    for device in pbar(devices):
        device['username'] = username
        device['password'] = password
        try:
            print(Fore.WHITE + '='*79 + Style.RESET_ALL)
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(current_time, '- Connecting to device:', device['ip'])

            # SSH into each device from "x.json" (2nd argument).
            connection = netmiko.ConnectHandler(**device)

            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            #success_connected = (current_time, '- Successfully connected -', device['ip'])
            success_connected = (current_time, '- Connection to device successful:', device['ip'])
            success_connected_str = ' '.join(success_connected)
            print(success_connected_str)
            print('-'*79)

            # Log the successful connection on the working directory in runner.log
            # Parse out the datestamp
            regex = r'(\d+/\d+/\d+\s+\d+:\d+:\d+\s+-\s+)(.*)'
            m_conn = re.match(regex, success_connected_str)
            logger.info(m_conn.group(2))

            # Get device's "hostname" from netmiko, and "ip" from .json
            hostname = connection.base_prompt
            ip = (device['ip'])

            # Log "start" locally on the device.
            sysargv = ' '.join(sys.argv)
            connection.send_command('send log 6 "Begin script: {}"'.format(sysargv))
            
            # Send each command from "x.txt" to device (3rd argument).
            for command in commands:
                # If only whitespace in line do nothing and continue.
                if command in ['\n', '\r\n']:
                    pass
                else:
                    print('[{0}] [{1}] >> {2}'.format(hostname, ip, command) + '\n')
                    print(connection.send_command(command))
                    print('\n' + '-'*79)

            # Log "end" locally on the device.
            connection.send_command('send log 6 "End script: {}"'.format(sysargv))

            # Disconnect SSH session.
            connection.disconnect()

            # Log the successful configuration on the working directory in runner.log
            success_configured = ('Configuration to device successful:', device['ip'])
            success_configured_str = ' '.join(success_configured)
            logger.info(success_configured_str)


        except netmiko_ex_auth as ex_auth:
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(Fore.RED + current_time, '- Authentication error:', device['ip'] + Style.RESET_ALL)
            # Log the authentication error on the working directory in runner.log
            logger.warning(ex_auth)

        except netmiko_ex_time as ex_time:
            current_timestamp = datetime.datetime.now()
            current_time = current_timestamp.strftime('%d/%m/%Y %H:%M:%S')
            print(Fore.RED + current_time, '- TCP/22 connectivity error:', device['ip'] + Style.RESET_ALL)
            # Log the TCP/22 connectivity error on the working directory in runner.log
            logger.warning(ex_time)


        # Script end timestamp and formatting
        end_timestamp = datetime.datetime.now()
        end_time = end_timestamp.strftime('%d/%m/%Y %H:%M:%S')

        # Script duration and formatting
        total_time = end_timestamp - start_timestamp
        total_time = str(total_time).split(".")[0]


        # SCRIPT STATISTICS
        print(Fore.WHITE + '='*79 + Style.RESET_ALL)
        print("+" + "-"*77 + "+")
        print("|" + " "*30 + "SCRIPT STATISTICS" +      " "*30 + "|")
        print("|" + "-"*77 + "|")
        print("| Script started:         ", start_time, " "*31 + "|")
        print("| Script ended:           ", end_time,   " "*31 + "|")
        print("| Script duration (h:m:s):", total_time, " "*43 + "|")
        print("+" + "-"*77 + "+")


if __name__ == "__main__":
    main()

#!/usr/bin/python ############################################################################### # Written by:           <NAME> # Creation date:        24/03/2018 # Last modified date:   19/08/2018 # Version:              v1.3 ############################################################################### # Standard library modules # Local modules # Logs on the working directory on the file named runner.log # If connection times out, the script will continue to run. # If authentication fails, the script will continue to run. # If arguments not equal to 3 we get an error. # Prompt for username and password # Progress Bar # Script start timestamp and formatting # SSH into each device from "x.json" (2nd argument). #success_connected = (current_time, '- Successfully connected -', device['ip']) # Log the successful connection on the working directory in runner.log # Parse out the datestamp # Get device's "hostname" from netmiko, and "ip" from .json # Log "start" locally on the device. # Send each command from "x.txt" to device (3rd argument). # If only whitespace in line do nothing and continue. # Log "end" locally on the device. # Disconnect SSH session. # Log the successful configuration on the working directory in runner.log # Log the authentication error on the working directory in runner.log # Log the TCP/22 connectivity error on the working directory in runner.log # Script end timestamp and formatting # Script duration and formatting # SCRIPT STATISTICS