How to get rid of dictionary number when dynamically building on - python

device_total={}
user_n="Cisco"
pwd= "test"
count=1
for i in range(0,31):
ip_addr= input('Please enter the device IP address' + ' : ')
dev_type = input (" Enter device type" + ' : ')
dsum = {'device type':dev_type,'host':ip_addr,'username':user_n,'password':pwd}
device_total[i] = dsum
i+1
query_user=input('Do you want to add additional devices? (y/n)' )
if query_user != 'y':
break
print(device_total)
I am trying to dynamically create multiple dictionaries based on a user input to be used to configure network devices with Netmiko, the dictionaries are built but every one of them is numbered which causes a line error when the Netmiko functions are trying to use them to log in a make configuration changes. Please let me know if there is a way to create the dictionary without them. I would like to create a separate dictionary for each device entered by the user not one with multiple entries. Thanks.
See example below:
{0: {'device type': 'cisco', 'host': '1.1.1.1', 'username': 'Cisco', 'password': 'test'}, 1: {'device type': 'Arista', 'host': '2.2.2.2', 'username': 'Cisco', 'password': 'test'}}

device_total=[]
user_n="Cisco"
pwd= "test"
count=1
for i in range(0,31):
ip_addr= input('Please enter the device IP address' + ' : ')
dev_type = input (" Enter device type" + ' : ')
dsum = {'device type':dev_type,'host':ip_addr,'username':user_n,'password':pwd}
device_total.append( dsum)
i+1
query_user=input('Do you want to add additional devices? (y/n)' )
if query_user != 'y':
break
print(device_total)

Here is the solution I came up with for anyone else that may in the same situation and stuck.
from getpass import getpass
from netmiko import ConnectHandler
from netmiko import NetmikoAuthenticationException
def user_input():
""" Getting user credentials """
usr_n = input("username: ")
pwd = getpass()
cred = (usr_n, pwd)
return cred
def net_devices():
login_info = user_input()
username = login_info[0]
password = login_info[1]
with open("districts devices.txt") as f:
net_devices = f.read().splitlines()
for device in net_devices:
try:
netw_devices = {"device_type": 'cisco_ios', 'host': device, 'username': username, 'password': password}
net_connect = ConnectHandler(**netw_devices)
except NetmikoAuthenticationException:
print(f"Unable to login to {device}. Verify you have the right credentials or it is added to ISE.")
continue
""" Verifying the access-list has been applied to the device. """
print('Verifying ACL the is on: ' + device)
verification = net_connect.send_command('show run | b line vty')
if "access-class" not in verification:
print("\nThe access-class is missing from this device's configuration. Configuring the ACL on: "
+ device)
acl_cmds = ['service password-encryption', 'ip access-list standard Sample-ONLY',
'permit 10.0.0.0 0.255.255.255',
' permit 172.16.0.0 0.0.255.255', 'line vty 0 15', 'transport in ssh',
'access-class sample in', 'do write memory']
commands = net_connect.send_config_set(acl_cmds)
print(commands)
else:
print("\nNo update necessary.\n")
# print(" \nVerifying the ACL is now in place.")
# re_verification = net_connect.send_command('\nshow run | b line vty')
# print(re_verification)
net_connect.disconnect()
net_devices()

Related

Use Netmiko to loop through file and get switch ARP entries

I am trying to output the ARP table of a switch by using Netmiko. I would like to use a file containing IP addresses and then have Python/Netmiko run a "show arp" and then add the IP address from the file I give. I would like it to loop through the IP address file to show all ARP entries for the IP addresses in the file and then output to a file containing both IP and MAC addresses. Below is what I have for a single address any help would be greatly appreciated:
#!/usr/bin/env python3
#CF extract ARP table and send output as text file
from netmiko import ConnectHandler
from datetime import datetime
import time
import sys
##initializing device
device = {
'device_type': 'hp_comware',
'ip': '10.1.10.10',
'username': 'xxxx',
'password': 'xxxx',
}
start_time = datetime.now()
print (start_time)
net_connect = ConnectHandler(**device)
output = net_connect.send_command("dis arp 172.16.100.100")
time.sleep(2)
filename="test-arp.txt"
saveconfig=open(filename, 'w+')
saveconfig.write(output)
saveconfig.close()
time.sleep(2)
net_connect.disconnect()
end_time = datetime.now()
print (end_time)
With the code below, you can perform the operation very quickly on 100 devices at the same time (you can increase it if you want) in accordance with the promt of the device.
from netmiko import Netmiko
from multiprocessing.dummy import Pool as ThreadPool
import time
f_2 = open("multiple_device_list_cisco.txt","r") # You should open a notepad with this name and add all the IPs one under the other.
multiple_device_list = f_2.readlines()
file1 = open("Result.txt", "a") # this will be your automatic output when the code is finished
def _ssh_(nodeip):
try:
hp = {
'device_type': 'hp_comware', 'ip': nodeip, 'username':
xxxx, 'password': xxxx, 'secret':xxxx, "conn_timeout": 20}
hp_connect = Netmiko(**hp)
print(nodeip.strip() + " " + "is reachable")
except Exception as e:
print (e)
f_3.write(nodeip.strip() + "\n")
return
prompt_hp_fnk = hp_connect.find_prompt()
hostname_fnk = prompt_hp_fnk.strip("#") # Here you should put whatever the prompt of your HP device is
print(hostname_fnk)
output = hp_connect.send_command_timing("dis arp "+ nodeip)
file1.write(nodeip +" "+ output+ "\n")
hp_connect.disconnect()
myPool = ThreadPool(100) # you can increase or decrease this value
result = myPool.map(_ssh_,multiple_device_list)
I wrote the necessary changes to the above code. I hope that will be useful

Automated interaction within ssh session

I need to collect some output via ssh from different devices but there are two caveats:
The devices are interactively asking for credentials so login can't be easily automated
The output is paged, so it is required to press "Enter" a number of times to get to the end of it
I've tried using paramiko_expect, I can manage the authentication but then I can't figure out how to loop in a while-like style.
from paramiko_expect import SSHClientInteraction
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(addresses[0], username = username, password = password, look_for_keys = False, allow_agent = False)
output = ""
with SSHClientInteraction(client, timeout = 10, display = False) as interact:
interact.expect(['User:.*'])
interact.send(username)
interact.expect(['Password:.*'])
interact.send(password)
interact.expect(['.*>'])
interact.send('get output')
interact.expect(['.*>','.*More or (q)uit.*'])
keepOnLooping = True
while keepOnLooping == True:
if interact.last_match == '.*More or (q)uit.*':
interact.send(interact.send(' '))
interact.expect(['.*>','.*More or (q)uit.*'])
keepOnLooping = True
elif interact.last_match == '.*>':
interact.send(interact.send(' '))
keepOnLooping = False
output = interact.current_output
I've tried with pexpect (pxssh) but I'm failing at the authentication phase.
from pexpect import pxssh
import getpass
try:
s = pxssh.pxssh()
hostname = input('hostname: ')
username = input('username: ')
password = getpass.getpass('password: ')
s.login(hostname, username, password)
s.expect('User:.*')
s.sendline(username)
s.expect('Password:.*')
s.sendline(password)
Any suggestions on how to automate the mentioned proceedures?

How can I make my current code use Multithreading/concurrent.futures?

I am new to netmiko/Python scripting , Using online examples was able to make a script to take configuration backup. The backup is copied to the text file and output is saved.
Currently this backup is done sequentially and it does not connect to all device at once and take the backup. I want to connect to all the devices concurrently.
I understand multithreading or concurrent.futures can solve this issueenter code here but I was not able to do it so far.
Can anyone please suggest, how my existing code can be modified to achieve it. Below is the code.
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException
from paramiko.ssh_exception import SSHException
from netmiko.ssh_exception import AuthenticationException
import getpass
import sys
import time
import os
from datetime import datetime
##getting system date
day=time.strftime('%d')
month=time.strftime('%m')
year=time.strftime('%Y')
today=day+"-"+month+"-"+year
enter code here
##initialising device
device = {
'device_type': 'cisco_ios',
'ip': '192.168.100.21',
'username': 'Cisco',
'password': 'Cisco',
'secret':'Cisco',
'session_log': 'log.txt'
}
##opening IP file
ipfile=open("iplist.txt")
print ("Script to take backup of devices, Please enter your credential")
device['username']=input("username ")
device['password']=getpass.getpass()
print("Enter enable password: ")
device['secret']=getpass.getpass()enter code here
##taking backup
for line in ipfile:
try:
device['ip']=line.strip("\n")
print("\n\nConnecting Device ",line)
net_connect = ConnectHandler(**device)
net_connect.enable()
time.sleep(1)
with open('config.txt') as f:
cmd = f.read().splitlines()
print ("Reading the running config ")
output = net_connect.send_config_set(cmd)
output4 = "Failed"
time.sleep(7)
filename=device['ip']+'-'+today+".txt"
folder = os.path.join(today)
file = os.path.join(folder,filename)
os.makedirs(folder,exist_ok=True)
saveconfig=open(file,'w+')
print("Writing Configuration to file")
saveconfig.write(output)
saveconfig.close()
time.sleep(10)
net_connect.disconnect()
print ("Configuration saved to file",filename)
except:
print ("Access to "+device['ip']+" failed,backup did not taken")
output4 = "Failed"
file= device['ip']+'-'+today+"Error"+".txt"
config=open(file,'w+')
config.write(output4)
config.close()
ipfile.close()
print ("\nAll device backup completed")enter code here
You can refer below script and modify it according to your requirement. Here I have used python multiprocessing for connecting devices in pools.
#This script will allow for user pick hosts and enter show commands interactively
#
#Enable Multiprocessing
from multiprocessing import Pool
#
#getpass will not display password
from getpass import getpass
#ConnectionHandler is the function used by netmiko to connect to devices
from netmiko import ConnectHandler
#Time tracker
from time import time
#create variables for username and password
#create variables for configs and hosts
uname = input("Username: ")
passwd = getpass("Password: ")
cmd = input("Enter show commands seperated by ',': ")
host = input("Enter the host IPs seperate with space: ")
#This will put hosts and commands entered into list format
hosts = host.split()
cmds = cmd.split(",")
starting_time = time()
#Each member of the pool of 5 will be run through this function
def run_script(host_ip):
ios_rtr = {
"device_type": "cisco_ios",
"ip": host_ip,
"username": uname,
"password": passwd,
}
#connect to the device via ssh
net_connect = ConnectHandler(**ios_rtr)
#print the device IP or Hostname
print("Connected to host:", host_ip)
#this for loop is used to iterate through the show commands
for show_commands in cmds:
output = net_connect.send_command(show_commands)
print("Connected to host:", host_ip)
print(output)
print('\n---- Elapsed time=', time()-starting_time)
if __name__ == "__main__":
# Pool(5) means 5 process will be run at a time, more hosts will go in the next group
with Pool(5) as p:
print(p.map(run_script, hosts))
#This is the key to sending show commands vs config commands
#show commands --> net_connect.send_command()
#config commmands --> net_connect.send_config_set()
With this code, you can run commands on many devices at the same time. You can also use it by hiding your identity information with user_pass. There is also a device prompt discovery feature.
with open("user_pass.txt", "r") as f5:
user_pass = f5.readlines()
for list_user_pass in user_pass:
if "username" in list_user_pass:
username = list_user_pass.split(":")[1].strip()
if "password" in list_user_pass:
password = list_user_pass.split(":")[1].strip()
def _ssh_(nodeip):
try:
access_mpls = {
'device_type': 'huawei_olt', 'ip': nodeip, 'username':
username, 'password': password, }
net_connect = Netmiko(**access_mpls)
print(nodeip.strip() + " " + "success enter")
except Exception as e:
print(e)
f_3.write(nodeip.strip() + "\n")
return
prompt_gpon_fnk = net_connect.find_prompt()
hostname_fnk = prompt_gpon_fnk.strip("<" + ">")
print(hostname_fnk)
net_connect.send_command_timing("enable")
net_connect.send_command_timing("undo smart")
output = net_connect.send_command_timing("config")
print("config moda girildi")
net_connect.send_command_timing("acl 2010 ")
net_connect.send_command_timing("quit")
net_connect.send_command_timing("save")
print("config done")
with open("MDU_OK_2.txt", "a") as f:
f.write(nodeip + "\n")
f.close()
net_connect.disconnect()
f_2 = open("ip_list_2.txt", "r") ip_list = f_2.readlines()
f_2.close() f_3 = open("ssh_unsuccess_2.txt", "w")
myPool = ThreadPool(100) result = myPool.map(ssh, ip_list)

Email is not being sent via python

I have created this piece of code as a test run to send an email over python:
import smtplib
import random
import math
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
ADMIN_EMAIL = email
ADMIN_PASS = password
def generate_ver_code():
digs = "0123456789"
code = ""
for i in range(0, 6):
code += digs[math.floor(random.random() * 10)]
return code
def signup(forename, surname, email, occupation, dob, pass1, pass2, pass_match):
ran_num = str(random.randint(0, 9999))
if len(ran_num) >= 4:
if len(ran_num) == 1:
ran_num = "000" + str(ran_num)
elif len(ran_num) == 2:
ran_num = "00" + str(ran_num)
elif len(ran_num) == 3:
ran_num = "0" + str(ran_num)
elif len(ran_num) == 4:
ver_code = str(ran_num)
username = ran_num + forename[:3] + surname[:3] + dob[:2]
if pass1 == pass2:
passw = pass1
pass_match = True
else:
pass_match = False
s = smtplib.SMTP('smtp.gmail.com', 5354)
#home port = 5354
#school port =
s.starttls()
s.login(ADMIN_EMAIL, ADMIN_PASS)
msg = MIMEMultipart()
message = message_template.substitute(PERSON_NAME=forename)
msg['From']=ADMIN_EMAIL
msg['To']=email
msg['Subject']="Verify account: FAKtory Reset"
msg.attach(MIMEText(message, '\nBefore you can continue to use your account please verify yur account and check if the credentials are correct:\nUsername: '+ username + '\nName: ' + forename + ' ' + surname + '\nOccupation: ' + occupation + '\nDoB: ' + dob + '\nPassword: ' + pass1 + '\nVerification Code: ' + ver_code + '\nIf any of the credentials are wrong please enter them again on our app.\nThank you,\nRegards,\nFaizan Ali Khan\nAdmin'))
s.send_message(msg)
del msg
pass_match = False
forename = str(input("Enter your forename: "))
surname = str(input("Enter your surname: "))
email = str(input("Enter your email: "))
occupation = str(input("Enter your occupation: "))
dob = str(input("Enter your date of birth (DD/MM/YYYY): "))
pass1 = str(input("Enter your password: "))
pass2 = str(input("Enter your password again: "))
print(signup(forename, surname, email, occupation, dob, pass1, pass2, pass_match))
Now whenever I run the code it goes fine for the inputs but when it comes to sending the email I get this error:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
How would you fix this error? I tried changing the port but still it doesn't work.
s = smtplib.SMTP('smtp.gmail.com', 5354)
The issue is this code snippet. According to the official Gmail IMAP Guide the outgoing port is either 465 or 587:
The outgoing SMTP server, smtp.gmail.com, requires TLS. Use port 465, or port 587 if your client begins with plain text before issuing the STARTTLS command.

mail-client issue in Python

My script should take the user inputs and login to the server but when I give it the inputs it false and I tried different servers and different emails and the passwords are correct. How can I determine what's wrong?
import smtplib
sent = 'true'
ss = 'true'
repeat = 1
while sent == 'true':
m_email = input ('Enter Your Email Address: ')
m_server = input ('Entere Your Email Server: ')
m_auth = input ('username?\n')
p_auth = input ('password?\n')
r_email = input ('enter the reciver email: ')
subject = input ('enter Your Subject: ')
subject = 'subject '+ subject
m_massege = input ('Your Massege: ')
massege = subject + '\n \n' + m_massege
while ss == 'true' or repeat == "5" :
try:
server = smtplib.SMTP(m_server)
server.ehlo()
server.starttls()
server.login(m_auth,p_auth)
server.Sendmail(m_email,r_mail,massege)
print ("Mail Sent Successfully!")
sent = 'false'
except:
print ('sending failed')
repeat =+ 1
exit()
I've also had issues with smtplib and what I found was that it was not actually a code issue but rather an issue with the email account. For example, in my case I was trying to log into my yahoo mail account to automate emails and it kept failing so I had to go to my yahoo account security settings and enable "allow unsecured application login".
Point is: the problem isn't with your code but with the security settings on the email accounts (For me neither gmail nor yahoo worked).

Categories

Resources