-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathservice_dumper.py
143 lines (100 loc) · 3.52 KB
/
service_dumper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'''Utility to dump all TR-064 service actions of a FritzBox including their
values.'''
from argparse import ArgumentParser
import csv
import logging
import fritzconnection as fc
from pfbex.settings import EnvSettingsResolver
SETTINGS_DESC = {
'FRITZ_HOST': {
'default': 'fritz.box',
'help': 'Hostname of the FritzBox to query.'
},
'FRITZ_USER': {
'required': True,
'help': 'Username to log in to the FritzBox to retrieve metrics'
},
'FRITZ_PASS': {
'required': True,
'help': 'Password to log in to the FritzBox to retrieve metrics'
},
}
def process_action(conn, service, action):
'''Handle one action'''
args = action.arguments.values()
inargs = sum(1 for arg in args if arg.direction == 'in')
outargs = sum(1 for arg in args if arg.direction == 'out')
if inargs:
logging.info(
f'Skipping {service.name}:{action.name} because it has input args.')
return
if not outargs:
logging.info(
f'Skipping {service.name}:{action.name} because it has no output '
'args.')
return
logging.debug(f'Retrieving {service.name}:{action.name}.')
try:
res = conn.call_action(service.name, action.name)
if not res:
logging.warning(
'No response returned when accessing '
f'{service.name}:{action.name}')
return
except Exception as ex: # pylint: disable=broad-except
logging.exception(
f'Failed to access {service.name}:{action.name}: {ex}')
return
for attr, val in res.items():
yield [service.name, action.name, attr, val]
def process_service(conn, service):
'''Handle a service'''
for action in service.actions.values():
yield from process_action(conn, service, action)
def process_all(conn):
'''Handle all services'''
for service in conn.services.values():
yield from process_service(conn, service)
def parse_args():
'''Parse command-line arguments and return the result.'''
parser = ArgumentParser()
parser.add_argument(
'csvfile',
type=str,
help='Write the query results to this file.')
parser.add_argument(
'-d', '--data',
action='store_true',
help=(
'Do dump service response data. By default the data is not included '
'in the dump to protect sensitive information'))
parser.add_argument(
'-v', '--verbose',
action='store_true',
help=('Log verbose information'))
return parser.parse_args()
def main():
'''Application entry point.'''
args = parse_args()
logging.basicConfig(
format='%(asctime)-15s %(levelname)s: %(message)s',
level=(logging.DEBUG if args.verbose else logging.INFO))
settings = EnvSettingsResolver(SETTINGS_DESC)
conn = fc.FritzConnection(
address=settings.FRITZ_HOST,
user=settings.FRITZ_USER,
password=settings.FRITZ_PASS)
results = []
results.extend(process_all(conn))
results.sort(key=lambda e: (e[0], e[1], e[2]))
with open(args.csvfile, 'w', newline='') as fhdl:
writer = csv.writer(fhdl)
writer.writerow(['Service', 'Action', 'Attribute', 'Value'])
for row in results:
if args.data:
writer.writerow(row)
else:
writer.writerow(row[0:3])
logging.info(f'Wrote {len(results)} services / actions to {args.csvfile}.')
if __name__ == '__main__':
main()