forked from sonic-net/sonic-utilities
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
executable file
·125 lines (101 loc) · 3.76 KB
/
main.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
#! /usr/bin/python -u
import click
import errno
import os
import pexpect
import subprocess
import sys
from click_default_group import DefaultGroup
try:
# noinspection PyPep8Naming
import ConfigParser as configparser
except ImportError:
# noinspection PyUnresolvedReferences
import configparser
# This is from the aliases example:
# https://github.com/pallets/click/blob/57c6f09611fc47ca80db0bd010f05998b3c0aa95/examples/aliases/aliases.py
class Config(object):
"""Object to hold CLI config"""
def __init__(self):
self.path = os.getcwd()
self.aliases = {}
def read_config(self, filename):
parser = configparser.RawConfigParser()
parser.read([filename])
try:
self.aliases.update(parser.items('aliases'))
except configparser.NoSectionError:
pass
# Global Config object
_config = None
# This aliased group has been modified from click examples to inherit from DefaultGroup instead of click.Group.
# DefaultGroup is a superclass of click.Group which calls a default subcommand instead of showing
# a help message if no subcommand is passed
class AliasedGroup(DefaultGroup):
"""This subclass of a DefaultGroup supports looking up aliases in a config
file and with a bit of magic.
"""
def get_command(self, ctx, cmd_name):
global _config
# If we haven't instantiated our global config, do it now and load current config
if _config is None:
_config = Config()
# Load our config file
cfg_file = os.path.join(os.path.dirname(__file__), 'aliases.ini')
_config.read_config(cfg_file)
# Try to get builtin commands as normal
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
# No builtin found. Look up an explicit command alias in the config
if cmd_name in _config.aliases:
actual_cmd = _config.aliases[cmd_name]
return click.Group.get_command(self, ctx, actual_cmd)
# Alternative option: if we did not find an explicit alias we
# allow automatic abbreviation of the command. "status" for
# instance will match "st". We only allow that however if
# there is only one command.
matches = [x for x in self.list_commands(ctx)
if x.lower().startswith(cmd_name.lower())]
if not matches:
# No command name matched. Issue Default command.
ctx.arg0 = cmd_name
cmd_name = self.default_cmd_name
return DefaultGroup.get_command(self, ctx, cmd_name)
elif len(matches) == 1:
return DefaultGroup.get_command(self, ctx, matches[0])
ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))
def run_command(command, display_cmd=False):
if display_cmd:
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
proc = pexpect.spawn(command)
proc.interact()
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '-?'])
#
# 'connect' group (root group)
#
# This is our entrypoint - the main "connect" command
@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS)
def connect():
"""SONiC command line - 'connect' command"""
pass
#
# 'line' command ("connect line")
#
@connect.command('line')
@click.argument('linenum')
def line(linenum):
"""Connect to line LINENUM via serial connection"""
cmd = "consutil connect " + linenum
run_command(cmd)
#
# 'device' command ("connect device")
#
@connect.command('device')
@click.argument('devicename')
def device(devicename):
"""Connect to device DEVICENAME via serial connection"""
cmd = "consutil connect -d " + devicename
run_command(cmd)
if __name__ == '__main__':
connect()