Skip to content

Commit

Permalink
Add 'config' CLI utility; rename 'sonic_cli' -> 'show' (sonic-net#46)
Browse files Browse the repository at this point in the history
- Add new 'config' command line utility which currently has the following functionality:
  - Can shut down/start up BGP session with neighbor by neighbor's IP or hostname
    - Example commands:
      - config bgp shutdown neighbor ARISTA02T1
      - config bgp startup neighbor 192.168.1.1
- Renamed 'sonic_cli' directory to 'show'
- Clean up temp files after use in 'show platform'  and 'show version'
  • Loading branch information
jleveque authored May 9, 2017
1 parent e188b5e commit 7f44592
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 3 deletions.
File renamed without changes.
152 changes: 152 additions & 0 deletions config/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/sbin/env python

import os
import click
import json
import subprocess

SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
MINIGRAPH_PATH = '/etc/sonic/minigraph.xml'
MINIGRAPH_BGP_ASN_KEY = 'minigraph_bgp_asn'
MINIGRAPH_BGP_SESSIONS = 'minigraph_bgp'

#
# Helper functions
#

# Returns BGP ASN as a string
def _get_bgp_asn_from_minigraph():
# Get BGP ASN from minigraph
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_ASN_KEY],
stdout=subprocess.PIPE,
shell=False,
stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
proc.wait()
return json.loads(stdout.rstrip('\n'))

# Returns True if a neighbor has the IP address <ipaddress>, False if not
def _is_neighbor_ipaddress(ipaddress):
# Get BGP ASN from minigraph
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_SESSIONS],
stdout=subprocess.PIPE,
shell=False,
stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
proc.wait()
bgp_session_list = json.loads(stdout.rstrip('\n'))

for session in bgp_session_list:
if session['addr'] == ipaddress:
return True

return False

# Returns string containing IP address of neighbor with hostname <hostname> or None if <hostname> not a neighbor
def _get_neighbor_ipaddress_by_hostname(hostname):
# Get BGP ASN from minigraph
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_SESSIONS],
stdout=subprocess.PIPE,
shell=False,
stderr=subprocess.STDOUT)
stdout = proc.communicate()[0]
proc.wait()
bgp_session_list = json.loads(stdout.rstrip('\n'))

for session in bgp_session_list:
if session['name'] == hostname:
return session['addr'];

return None


# Run bash command and print output to stdout
def run_command(command, pager=False):
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
if pager is True:
click.echo_via_pager(p.stdout.read())
else:
click.echo(p.stdout.read())
p.wait()
if p.returncode != 0:
sys.exit(p.returncode)


# This is our main entrypoint - the main 'config' command
@click.group()
def cli():
"""SONiC command line - 'config' command"""
pass


#
# 'bgp' group
#

@cli.group()
def bgp():
"""BGP-related tasks"""
pass

#
# 'shutdown' subgroup
#

@bgp.group()
def shutdown():
"""Shut down BGP session(s)"""
pass


# 'neighbor' subcommand
@shutdown.command()
@click.argument('ipaddr_or_hostname', required=True)
def neighbor(ipaddr_or_hostname):
"""Shut down BGP session by neighbor IP address or hostname"""
bgp_asn = _get_bgp_asn_from_minigraph()

if _is_neighbor_ipaddress(ipaddr_or_hostname):
ipaddress = ipaddr_or_hostname
else:
# If <ipaddr_or_hostname> is not the IP address of a neighbor, check to see if it's a hostname
ipaddress = _get_neighbor_ipaddress_by_hostname(ipaddr_or_hostname)

if ipaddress == None:
print "Error: could not locate neighbor '{}'".format(ipaddr_or_hostname)
raise click.Abort

command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} shutdown'".format(bgp_asn, ipaddress)
run_command(command)


@bgp.group()
def startup():
"""Start up BGP session(s)"""
pass


# 'neighbor' subcommand
@startup.command()
@click.argument('ipaddr_or_hostname', required=True)
def neighbor(ipaddr_or_hostname):
"""Start up BGP session by neighbor IP address or hostname"""
bgp_asn = _get_bgp_asn_from_minigraph()

if _is_neighbor_ipaddress(ipaddr_or_hostname):
ipaddress = ipaddr_or_hostname
else:
# If <ipaddr_or_hostname> is not the IP address of a neighbor, check to see if it's a hostname
ipaddress = _get_neighbor_ipaddress_by_hostname(ipaddr_or_hostname)

if ipaddress == None:
print "Error: could not locate neighbor '{}'".format(ipaddr_or_hostname)
raise click.Abort

command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {} shutdown'".format(bgp_asn, ipaddress)
run_command(command)


if __name__ == '__main__':
cli()

8 changes: 8 additions & 0 deletions data/etc/bash_completion.d/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
_config_completion() {
COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \
COMP_CWORD=$COMP_CWORD \
_CONFIG_COMPLETE=complete $1 ) )
return 0
}

complete -F _config_completion -o default config;
8 changes: 5 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
url='https://github.com/Azure/sonic-utilities',
maintainer='Joe LeVeque',
maintainer_email='jolevequ@microsoft.com',
packages=['sonic_cli', 'sonic_eeprom', 'sonic_sfp', "sonic_installer"],
packages=['config', 'show', 'sonic_eeprom', 'sonic_sfp', "sonic_installer"],
package_data={
'sonic_cli': ['aliases.ini']
'show': ['aliases.ini']
},
scripts=[
'scripts/aclshow',
Expand All @@ -27,12 +27,14 @@
'scripts/teamshow',
],
data_files=[
('/etc/bash_completion.d', ['data/etc/bash_completion.d/config']),
('/etc/bash_completion.d', ['data/etc/bash_completion.d/show']),
('/etc/bash_completion.d', ['data/etc/bash_completion.d/sonic_installer']),
],
entry_points={
'console_scripts': [
'show = sonic_cli.main:cli',
'config = config.main:cli',
'show = show.main:cli',
'sonic_installer = sonic_installer.main:cli'
]
},
Expand Down
Empty file added show/__init__.py
Empty file.
File renamed without changes.
5 changes: 5 additions & 0 deletions sonic_cli/main.py → show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ def summary():
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
click.echo(p.stdout.read())

# Clean up
os.remove(PLATFORM_TEMPLATE_FILE)

# 'syseeprom' subcommand ####
@platform.command()
def syseeprom():
Expand Down Expand Up @@ -316,6 +319,8 @@ def version():
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
click.echo(p.stdout.read())

# Clean up
os.remove(VERSION_TEMPLATE_FILE)

#
# 'environment' command ###
Expand Down

0 comments on commit 7f44592

Please sign in to comment.