Skip to content

Commit b665e0d

Browse files
committed
[devutils] add utilities to handle devices
- list hosts defined in an inventory. - ping hosts defined in an inventory. - ssh to host(s) define din an inventory. (best executed with limited to one host) - console connect to host(s). (not implemetned, for future expansion) Signed-off-by: Ying Xie <ying.xie@microsoft.com>
1 parent 812ab09 commit b665e0d

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

ansible/devutils

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
import os
5+
import subprocess
6+
from inv_helpers import get_host_list
7+
8+
9+
def run_cmd(cmd):
10+
'''
11+
@summary: Utility that runs a command in a subprocess
12+
@param cmd: Command to be run
13+
@return: stdout of the command run
14+
@return: stderr of the command run
15+
'''
16+
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
17+
stdout, stderr = out.communicate()
18+
return out.returncode, stdout, stderr
19+
20+
21+
def action_list(kind, host, details, parameters):
22+
print('type {} host {} details {}'.format(kind, host, details))
23+
24+
25+
def action_ping(kind, host, details, parameters):
26+
if not details or type(details) != dict:
27+
return
28+
29+
if 'ansible_host' in details:
30+
addr = details['ansible_host']
31+
rc, _, _ = run_cmd('ping -q -c 1 -w 1 {}'.format(addr))
32+
if rc != 0:
33+
print('host {} (type {}) is unreachable at address {}'.format(host, kind, addr))
34+
if parameters['ipv6'] and 'ansible_hostv6' in details:
35+
addr = details['ansible_hostv6']
36+
rc, _, _ = run_cmd('ping -6 -q -c 1 -w 1 {}'.format(addr))
37+
if rc != 0:
38+
print('host {} (type {}) is unreachable at address {}'.format(host, kind, addr))
39+
40+
41+
def action_ssh(kind, host, details, parameters):
42+
if not details or type(details) != dict:
43+
return
44+
45+
if 'ansible_host' in details:
46+
addr = details['ansible_host']
47+
os.system('ssh {}@{}'.format(parameters['user'], addr))
48+
49+
50+
def action_console(kind, host, details, parameters):
51+
print('Action console is not implemented')
52+
53+
54+
def hosts_walker(parameters):
55+
hosts = parameters['hosts']
56+
limit = parameters['limit']
57+
for key, val in hosts.items():
58+
for host, details in val.items():
59+
if limit == 'all' or limit == host:
60+
parameters['action'](key, host, details, parameters)
61+
62+
63+
def main():
64+
parser = argparse.ArgumentParser(description='Device utilities')
65+
parser.add_argument('-6', '--ipv6', help='Include IPv6', action='store_true',
66+
required=False, default=False)
67+
parser.add_argument('-a', '--action',
68+
help='Action towards host(s): list, ping, ssh, console, default list',
69+
type=str, required=False, default='list',
70+
choices=['list', 'ping', 'ssh', 'console'])
71+
parser.add_argument('-c', '--category', help='Categories: all, sonic, ptf, pdu, default all',
72+
type=str, required=False, default='all')
73+
parser.add_argument('-i', '--inventory', help='Categories: lab, etc, default lab',
74+
type=str, required=False, default='lab')
75+
parser.add_argument('-l', '--limit', help='Host: limit to a single dut host name, default all',
76+
type=str, required=False, default='all')
77+
parser.add_argument('-u', '--user', help='User: user account to login to host with, default admin',
78+
type=str, required=False, default='admin')
79+
80+
args = parser.parse_args()
81+
82+
hosts = get_host_list(args.inventory, args.category)
83+
actions = { 'list' : action_list,
84+
'ping' : action_ping,
85+
'ssh' : action_ssh,
86+
'console' : action_console,
87+
}
88+
parameters = { 'hosts' : hosts,
89+
'limit' : args.limit,
90+
'action' : actions[args.action],
91+
'user' : args.user,
92+
'ipv6' : args.ipv6,
93+
}
94+
hosts_walker(parameters)
95+
96+
97+
if __name__ == '__main__':
98+
main()

ansible/inv_helpers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import yaml
2+
3+
4+
def get_all_hosts(inventory):
5+
hosts = {}
6+
for key, val in inventory.items():
7+
vtype = type(val)
8+
if vtype == dict:
9+
if 'hosts' in val:
10+
hosts.update({ key : val['hosts'] })
11+
else:
12+
hosts.update(get_all_hosts(val))
13+
return hosts
14+
15+
16+
def get_host_list(inventory, category):
17+
with open(inventory, 'r') as file:
18+
inv = yaml.safe_load(file)
19+
20+
all_hosts = get_all_hosts(inv)
21+
hosts = {}
22+
for key, val in all_hosts.items():
23+
if category == 'all' or category in key:
24+
hosts.update({key : val})
25+
26+
return hosts
27+

0 commit comments

Comments
 (0)