netmiko connections from device list is only connecting to first ip in list - netmiko

Im using
(base) C:\python
Python 3.8.8 (default, Apr 13 2021, 15:08:03) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.sing
Created on Wed Jun 16 10:15:59 2021
import logging
from netmiko import ConnectHandler
logging.basicConfig(filename='test2.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
with open('host.txt', "r") as host:
for ip in host.read().splitlines():
cisco = {
'device_type': 'cisco_ios',
'ip': ip,
'username': 'user',
'password': 'password',
}
net_connect = ConnectHandler(**cisco)
print (' #### Connecting to ' + ip)
output = net_connect.find_prompt()
print(output)
net_connect.disconnect()

You need to create a for loop. Netmiko accepts one dictionary within the ConnectHandler class. So to make the code run "for each" device, you have to create a loop.
Also, in the for loop you created to read the IP addresses from hosts.txt, you keep overwriting the cisco dict every time in the loop. cisco = {} overwrites the previous value each time. New values should be appended to a list instead.
You can achieve this by doing:
from netmiko import ConnectHandler
import logging
logging.basicConfig(filename="test2.log", level=logging.DEBUG)
logger = logging.getLogger("netmiko")
with open(file="hosts.txt", mode="r") as hosts:
# A list comprehension
devices = [
{
"device_type": "cisco_ios",
"ip": ip,
"username": "cisco",
"password": "cisco",
}
for ip in hosts.read().splitlines()
]
print(devices) # <--- print value is below
# Connect to each device (one at a time)
for device in devices:
print(f'Connecting to {device["ip"]}') # Here you are still trying to connect
net_connect = ConnectHandler(**device)
print(f'Connected to {device["ip"]}') # Here you are already connected
prompt = net_connect.find_prompt()
net_connect.disconnect() # disconnect from the session
# Finally, print the prompt within the foor loop, but
# after you disconnect. You no longer need the connection to print.
print(prompt)
You can forget about net_connect.disconnect() by using with statement (Context Manager)
It's important to clear the vty line after you are done
for device in devices:
print(f'Connecting to {device["ip"]}') # Here you are still waiting to connect
with ConnectHandler(**device) as net_connect:
print(f'Connected to {device["ip"]}') # Here you are already logged-in
prompt = net_connect.find_prompt()
print(prompt)
If you print the devices list, you will get:
[{'device_type': 'cisco_ios',
'ip': '192.168.1.1', # From hosts.txt file
'password': 'cisco',
'username': 'cisco'},
{'device_type': 'cisco_ios',
'ip': '192.168.1.2', # From hosts.txt file
'password': 'cisco',
'username': 'cisco'}]

Related

Netmiko / textfsm

'Hello, i got my information parsed the way I want it. But now I'm trying to save the output
to a possible .txt file. Im not sure what to type in the "backup.write()" if I type the
"output" variable it saves the whole output not the parsed section.'
connection = ConnectHandler(**cisco_device)
# print('Entering the enable mode...')
# connection.enable()
prompt = connection.find_prompt()
hostname = prompt[0:-1]
print(hostname)
output = connection.send_command('show interfaces status', use_textfsm=True)
for interface in output:
if interface['status'] == 'notconnect':
print(f"interface {interface['port']} \n shutdown")
print(hostname)
print('*' * 85)
# minute = now.minute
now = datetime.now()
year = now.year
month = now.month
day = now.day
hour = now.hour
# creating the backup filename (hostname_date_backup.txt)
filename = f'{hostname}_{month}-{day}-{year}_backup.txt'
# writing the backup to the file
with open(filename, 'w') as backup:
backup.write()
print(f'Backup of {hostname} completed successfully')
print('#' * 30)
print('Closing connection')
connection.disconnect()
my desired result is to run the Cisco IOS command "show interface status" and parse the data using textfsm module to only provide the interfaces that are in the shtudown.
I tried the same on show ip interface brief, because I have no access to a Cisco switch right now. For show interfaces status both methods apply but with different output modifier or if condition.
So to get the following output, you can do it in two ways:
1- CLI Output Modifier
show ip interface brief | include down
And the rest is left for TextFSM to parse the output
[{'intf': 'GigabitEthernet2',
'ipaddr': 'unassigned',
'proto': 'down',
'status': 'administratively down'},
{'intf': 'GigabitEthernet3',
'ipaddr': '100.1.1.1',
'proto': 'down',
'status': 'down'}]
2- Python
You can get the whole output from show ip interface brief and loop over all parsed interfaces and set an if condition to get the down interfaces only. (Recommended)
# Condition for `show ip interface brief`
down = [
intf
for intf in intfs
if intf["proto"] == "down" or intf["status"] in ("down", "administratively down")
]
# Condition for `show interfaces status`
down = [
intf
for intf in intfs
if intf["status"] == "notconnect"
]
Exporting a List[Dict] to a .txt file makes no sense. You don't have any syntax highlighting or formatting in .txt files. It's better to export it to a JSON file. So a complete example of what you want to achieve can be something like:
import json
from datetime import date
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"ip": "x.x.x.x",
"username": "xxxx",
"password": "xxxx",
"secret": "xxxx",
}
with ConnectHandler(**device) as conn:
print(f'Connected to {device["ip"]}')
if not conn.check_enable_mode():
conn.enable()
hostname = conn.find_prompt()[:-1]
intfs = conn.send_command(
command_string="show ip interface brief", use_textfsm=True
)
print("Connection Terminated")
down = [
intf
for intf in intfs
if intf["proto"] == "down" or intf["status"] in ("down", "administratively down")
]
with open(file=f"{hostname}_down-intfs_{date.today()}.json", mode="w") as f:
json.dump(obj=down, fp=f, indent=4)
print(f"Completed backup of {hostname} successfully")
# In case you have to export to text file
# with open(file=f"{hostname}_down-intfs_{date.today()}.txt", mode="w") as f:
# f.write(down)
# print(f"Completed backup of {hostname} successfully")

Implementation error for type bool when writing custom Ansible module

I'm trying to write a custom module in Ansible 2.3 to use in my playbook. The details of it has been abstracted to run a minimal date command below, but I'm developing a much complicated example.
[dev#foobar Gist]$ tree ansible_version_err/
ansible_version_err/
├── dev_command.yml
└── library
└── dev_command.py
The contents of the library file is using the ansible.module package to implement the custom command.
#!/usr/bin/python
from ansible.module_utils.basic import *
from subprocess import Popen, PIPE
import time
if __name__ == '__main__':
module = AnsibleModule(
argument_spec={
'command': { 'type':'str', 'required': True },
'print_elapsed': { 'type':bool, 'required': False },
'print_time': { 'type':bool, 'required': False } } )
stdout = None
stderr = None
rc = None
try:
time_start = time.time()
proc = Popen( module.params['command'], shell = True)
stdout, stderr = proc.communicate()
time_end = time.time()
rc = proc.returncode
if rc != 0:
raise Exception("error while obtaining date")
time_elapsed = time_end - time_start
if 'print_elapsed' in module.params and module.params['print_elapsed']:
stdout = stdout + "\nelapsed time: " + str(time_elapsed)
if 'print_time' in module.params and module.params['print_time']:
stdout = stderr + "\ntime: " + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(time_start))
module.exit_json( changed = False, stdout = stdout, stderr = stderr, rc = rc, time_elapsed = time_elapsed )
except Exception:
pass
and the .yml file using this dev_command is called as
---
- hosts: localhost
gather_facts: no
tasks:
- name: testing a custom command
vars:
print_stdout: True
dev_command: command="{{cmd}}" print_elapsed=True print_time=True
I'm just calling the cmd with date which will go ahead and run the date command.
ansible-playbook dev_command.yml -vvv -e "cmd=date"
While I expect this work on Ansible 2.3, it is throwing me an error as
fatal: [localhost]: FAILED! => {
"changed": false,
"failed": true,
"invocation": {
"module_args": {
"command": "date",
"print_elapsed": "True",
"print_time": "True"
}
},
"msg": "implementation error: unknown type <type 'bool'> requested for print_time"
}
This error is not seen in v2.6. Why is this happening? Is this a known Ansible feature bug that can only be resolved by moving to a newer version. Version details
$ ansible --version
ansible 2.3.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
python version = 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
Q: "On Ansible 2.3, it is throwing me an error ... This error is not seen in v2.6. Why is this happening? Is this a known Ansible feature bug that can only be resolved by moving to a newer version?"
A: Yes. It's necessary to move to a maintained version. Even if it was a known problem it wouldn't be fixed anymore. Ansible Release cycle says:
"Ansible has a graduated maintenance structure that extends to three major releases ... we strongly encourage you to upgrade as soon as possible ..."
The latest Ansible version is 2.9 at the moment. The last maintained version is 2.7 at the moment.
FWIW. The command
$ grep -r type /scratch/ansible/lib/ansible/modules/ | grep bool | grep defaul
shows all modules declare the type Boolean with quotation
type='bool'
or
'type': 'bool'

paho-mqtt authentication error on pythonanywher

I am trying to publish to an mqtt topic on beebotte.com using a simple publish.single on my linux machine it works fine but on python anywhere I get an authentication error. There are small differences in minor version numbers, can that be what is different?
This is the code I put into the python console:
import paho.mqtt.publish as publish
mqtt_host = "beebotte.com"
mqtt_topic = "climate/set/livingroom"
auth = {'username':"token:MY_SECRET_TOKEN"}
publish.single(mqtt_topic, "python sent", hostname=mqtt_host, auth = auth)
this is the error:
Python 2.7.6 (default, Oct 26 2016, 20:30:19)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import paho.mqtt.publish as publish
>>> mqtt_host = "beebotte.com"
>>> mqtt_topic = "climate/set/livingroom"
>>> auth = {'username':"MY_SECRET_TOKEN"}
>>> publish.single(mqtt_topic, "python sent", hostname=mqtt_host, auth = auth)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/<MYUSER>/python-email/local/lib/python2.7/site-packages/paho/mqtt/publish.py", line 216, in single
protocol, transport)
File "/home/<MYUSER>/python-email/local/lib/python2.7/site-packages/paho/mqtt/publish.py", line 152, in multiple
client.connect(hostname, port, keepalive)
File "/home/<MYUSER>/python-email/local/lib/python2.7/site-packages/paho/mqtt/client.py", line 768, in connect
return self.reconnect()
File "/home/<MYUSER>/python-email/local/lib/python2.7/site-packages/paho/mqtt/client.py", line 895, in reconnect
sock = socket.create_connection((self._host, self._port), source_address=(self._bind_address, 0))
File "/usr/lib/python2.7/socket.py", line 571, in create_connection
raise err
socket.error: [Errno 111] Connection refused
>>>
>>> exit()
and here it is working:
Python 2.7.13 (default, Nov 24 2017, 17:33:09)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import paho.mqtt.publish as publish
>>> mqtt_host = "beebotte.com"
>>> mqtt_topic = "climate/set/livingroom"
>>> auth = {'username':"MY_SECRET_TOKEN"}
>>> publish.single(mqtt_topic, "python sent", hostname=mqtt_host, auth = auth)
>>>
>>> exit()
edit (I'm not sure if this is true):
The key is in the actual format of token:token_KxDxlcmXgQBDfWRNC (not real) beebotte.com also accepts a so-called secret key in the format of 2A4Gfgv0puYFBEVbBQX24szALcyDvMRh If I use the secret key it works from pythonanywhere (sometimes). This is leading me to beleive it is some kind of formatting problem with the : in the token.
So the question now is how to format it to work properly.
I don't think mqtt will work from a free account on PythonAnywhere. Free accounts can only connect out through a proxy using http(s) to a specific whitelist of sites. If there's an http to mqtt bridge somewhere, you could possibly use that.

Odoo 11 No Module Found

Hi I am new to odoo and linux ubuntu 16.04 LTS, I had set up the ubuntu desktop on an oracle vm virtualbox, I have also installed the necessary repository and apt for odoo11, postgresql, python3 and pycharm.
My odoo11 is already working fine and I am able to install and run existing applications, however I have tried to generate a scaffold to develop a module of my own, and I have followed guides and documentations.
My odoo.conf has these options
[options]
; This is the password that allows database operations:
; admin_passwd = admin
db_host = False
db_port = False
db_user = odoo
db_password = False
logfile = /var/log/odoo/odoo-server.log
addons_path = /opt/odoo/odoo/addons,/home/mtsoftware/Documents/projects/tutorial/addons
while my manifest.py has these option
# -*- coding: utf-8 -*-
{
'name': "myfirstModel",
'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
'description': """
Long description of module's purpose
""",
'author': "My Company",
'website': "http://www.yourcompany.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/master/odoo/addons/base/module/module_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['base'],
# always loaded
'data': [
# 'security/ir.model.access.csv',
'views/customer.xml',
],
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
}
Upon trying to search for "myfirstModel" in my module list # odoo11 application page, it returns a "No module found!"
Any one can help me?

Python EOF shortcut on Windows

Hello i worte this simple program for encripting stings.
It requires from user to enter a simple string after doing that user shoud hit EOF shortcut (CTRL+D or CTRL+Z) but nothing than entering ^D or ^Z happens. Everything is fine when I do this on Ubuntu (using CTRL+D), but on windows this problem occurs. (Windows 10, python 2.7) Is there any other way to enter EOF in userinput in console.
Program:
import string
table = string.maketrans("abcdefghijklmnopqrstuvwxyz", "nopqrstuvwxyzabcdefghijklm")
import fileinput
for line in fileinput.input():
line = line.rstrip()
print string.translate(line, table)
You can use sys.stdin.readline() that provides automatic EOL
Once you hit CTRL D , the program will quit gracefully.
Modified Code
import string
import atexit
import sys
#import fileinput
table = string.maketrans("abcdefghijklmnopqrstuvwxyz", "nopqrstuvwxyzabcdefghijklm")
while True:
line = sys.stdin.readline() #readline returns EOF by default after read
if line: #If data is read
line = line.rstrip() #read line and remove whitespace
print string.translate(line, table) #print translated string
else:
sys.exit(0) #exit on 'CTRL D'
Program Output
Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
wefjdjbgngfpbgf
jrswqwotatscots
jgnfrejgrtnhkeritrevndsksdlv
wtaserwtegauxrevgeriaqfxfqyi
>>>

Resources