Hey everyone,
sorry if the question is silly but I am so new to Python and I though I ask for some help.
I have created a function to use hashicorp and login to the list of switches which will provided in a text file.
I am not able to call net_connect which suppose to run the commands.
Therefor I won’t get any error nor I can send the command.
When all the codes are in the same file, the work fine and no problem but I am not able to separate them so I can use the login function in any other file I am using for different purposes.
your help is much appreciated.
Thanks
Ben.
login.py
import hvac
from netmiko import ConnectHandler
def login():
# Connect to Vault
vault_addr = "http://127.0.0.1:8200"
#vault_token = getpass.getpass("Enter your Vault token: ")
vault_token = "hXXXXXXXXXXXXXXXXXXXX"
client = hvac.Client(url=vault_addr, token=vault_token)
# Retrieve credentials from Vault
secret_path = "passwords"
secret = client.secrets.kv.v2.read_secret_version(path=secret_path)
username = secret['data']['data']['myuser']
password = secret['data']['data']['mypass']
#SSH to multpile devices
#create device template
with open("SwitchIPList.txt") as switches:
for IP in switches:
Switch = {
"device_type": "cisco_ios",
"ip": IP,
"username": username,
"password": password,
}
#Switch = perform_login.Switch #IP = perform_login.ip
net_connect = ConnectHandler(**Switch)
############################## Connect to IP ##############################
print("*“90)
print (“Connecting to " + IP)
print(””*90)
main.py
from netmiko import ConnectHandler
from login import *
import subprocess
def main():
“”"
Main Application Logic
“”"
########################## Confgis Logging & NTP ###########################
config_commands = [
"logging host 192.168.99.240",
"logging trap informational",
"logging file flash:logfile.text 25000 informational",
"service timestamp log datetime year",
"ip name-server 8.8.8.8",
"ntp server 0.uk.pool.ntp.org",
"ntp server 1.uk.pool.ntp.org",
"ntp server 2.uk.pool.ntp.org"
]
if __name__ == "__main__":
output = login.net_connect.send_config_set(config_commands)
print(output)
print("-"*72)
output = login.net_connect.send_command("show run | include logging")
print(output)
print("-"*72)
output = login.net_connect.send_command("wr")
print(output)
print("-"*72)
print("="*27,"END OF SWITCH","="*27)
#Close the connection
login.net_connect.disconnect()
Hi, it’s difficult to read the posted code (you really should use the preformatted text option, please see the quick start tutorial).
Besides, it’s better to include error messages or at least a detailed description of what does not work.
Sorry, but “I am not able to call net_connect” is really vague.
Anyway, and supposing that the posted code is complete, then I think you’re using Python as if it where a declarative configuration language, like Terraform, where declaring something sort of ‘executes’ and activates it.
In Python, the def login() lines just define a function, but to make it live you need to explicitly execute it by calling login().
During execution the function creates a variable net_connect, but it is internal to the function, thus not visible outside.
To use externally you should return it. Note, however, that the for IP in switches loop will overwrite net_connect with every iteration.
A better solution would be to pass a list of command to execute as a parameter
Hey, Thanks for explanation and, I am sorry, that I send the code incorrectly.
I am calling the function in the second file, and it run the code, but I am still not able to call the net_connect.
I tried adding return net_connect but still nothing will happens.
I am not recieving any errors which make me stuck in what to make out of it.
I know it is a dummy question, but I am still a dummy
This is the first file (login.py):
import hvac
from netmiko import ConnectHandler
def login():
# Connect to Vault
vault_addr = "http://127.0.0.1:8200"
#vault_token = getpass.getpass("Enter your Vault token: ")
vault_token = "XXXXXXXXXXXXXXXX"
client = hvac.Client(url=vault_addr, token=vault_token)
# Retrieve credentials from Vault
secret_path = "passwords"
secret = client.secrets.kv.v2.read_secret_version(path=secret_path)
username = secret['data']['data']['myuser']
password = secret['data']['data']['mypass']
#SSH to multpile devices
#create device template
with open("SwitchIPList.txt") as switches:
for IP in switches:
Switch = {
"device_type": "cisco_ios",
"ip": IP,
"username": username,
"password": password,
}
#Switch = perform_login.Switch
#IP = perform_login.ip
############################## Connect to IP ##############################
print("*"*90)
print ("Connecting to " + IP)
print("*"*90)
net_connect = ConnectHandler(**Switch)
return net_connect
This is the main file (main.py)
from netmiko import ConnectHandler
from login import *
login()
def main():
########################## Confgis Logging & NTP ###########################
config_commands = [
"logging host 192.168.99.240",
"logging trap informational",
"logging file flash:logfile.text 25000 informational",
"service timestamp log datetime year",
"ip name-server 8.8.8.8",
"ntp server 0.uk.pool.ntp.org",
"ntp server 1.uk.pool.ntp.org",
"ntp server 2.uk.pool.ntp.org"
]
output = login.net_connect.send_config_set(config_commands)
print(output)
print("-"*72)
output = login.connect.send_command("show run | include logging")
print(output)
print("-"*72)
output = login.net_connect.send_command("wr")
print(output)
print("-"*72)
print("="*27,"END OF SWITCH","="*27)
#Close the connection
login.net_connect.disconnect()
ok, there are a few problems with the posted code:
login() function:
with open(...) as switches opens the file and associates it to a variable switches, but not reads it
the for IP in switches loop covers only the Switch declaration. All it does is repeatedly overwrite the Switch variable.
after the loop, the Switch variable contains the last switch from the file; only a single ‘Connecting to’ line will be printed.
net_connect is constructed and returned using the information of the last Switch ip
by convention, Python variables start with a lower case letter, so it should be switch, not Switch.
Only classes start with an Upper case
Constants are ALL CAPS
main.py:
login() is called but the result of the function is not used. It could be something like netconn = login()
nobody calls main()
at minimum, the file should end with a line
if __name__ == "__main__":
main()
main() function:
it tries to access a not existent login.net_connect property of function login.
It should use something like the netconn variable in the example above, e.g. output = netconn.send_config_set(config_commands)
It would still work only for the last ip, however
To handle it properly, perhaps a working barebones solution would be:
modify login() to return a list of connections
modify main() to call login and iterate over the list of connections, using the current connection to send command.
More or less this:
def login():
... (setup)
connections = []
with open("SwitchIPList.txt") as f:
switches = f.readlines() # assuming an IP per line, no blanks
for IP in switches:
...
connections.append(ConnectHandler(**Switch))
return connections
def main():
... (config_commands declaration)
connections = login()
for connection in connections:
output = connection.send_config_set(config_commands)
... (rest of commands)
if __name__ == "__main__":
main()