Skip to content

Commit 98bc75e

Browse files
authored
Add 'config bgp shutdown all' and 'config bgp startup all' commands (sonic-net#78)
1 parent 5d8f98e commit 98bc75e

File tree

1 file changed

+110
-39
lines changed

1 file changed

+110
-39
lines changed

config/main.py

+110-39
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,35 @@
66
import json
77
import subprocess
88

9-
SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
10-
MINIGRAPH_PATH = '/etc/sonic/minigraph.xml'
11-
MINIGRAPH_BGP_ASN_KEY = 'minigraph_bgp_asn'
12-
MINIGRAPH_BGP_SESSIONS = 'minigraph_bgp'
9+
SONIC_CFGGEN_PATH = "/usr/local/bin/sonic-cfggen"
10+
MINIGRAPH_PATH = "/etc/sonic/minigraph.xml"
11+
MINIGRAPH_BGP_ASN_KEY = "minigraph_bgp_asn"
12+
MINIGRAPH_BGP_SESSIONS = "minigraph_bgp"
13+
14+
BGP_ADMIN_STATE_YML_PATH = "/etc/sonic/bgp_admin.yml"
1315

1416
#
1517
# Helper functions
1618
#
1719

20+
# Run bash command and print output to stdout
21+
def run_command(command, pager=False, display_cmd=False):
22+
if display_cmd == True:
23+
click.echo(click.style("Running command: ", fg='cyan') + click.style(command, fg='green'))
24+
25+
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
26+
stdout = p.communicate()[0]
27+
p.wait()
28+
29+
if len(stdout) > 0:
30+
if pager is True:
31+
click.echo_via_pager(p.stdout.read())
32+
else:
33+
click.echo(p.stdout.read())
34+
35+
if p.returncode != 0:
36+
sys.exit(p.returncode)
37+
1838
# Returns BGP ASN as a string
1939
def _get_bgp_asn_from_minigraph():
2040
# Get BGP ASN from minigraph
@@ -28,7 +48,7 @@ def _get_bgp_asn_from_minigraph():
2848

2949
# Returns True if a neighbor has the IP address <ipaddress>, False if not
3050
def _is_neighbor_ipaddress(ipaddress):
31-
# Get BGP ASN from minigraph
51+
# Get BGP sessions from minigraph
3252
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_SESSIONS],
3353
stdout=subprocess.PIPE,
3454
shell=False,
@@ -43,9 +63,29 @@ def _is_neighbor_ipaddress(ipaddress):
4363

4464
return False
4565

66+
# Returns list of strings containing IP addresses of all BGP neighbors
67+
def _get_all_neighbor_ipaddresses():
68+
# Get BGP sessions from minigraph
69+
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_SESSIONS],
70+
stdout=subprocess.PIPE,
71+
shell=False,
72+
stderr=subprocess.STDOUT)
73+
stdout = proc.communicate()[0]
74+
proc.wait()
75+
bgp_session_list = json.loads(stdout.rstrip('\n'))
76+
77+
bgp_neighbor_ip_list =[]
78+
79+
for session in bgp_session_list:
80+
bgp_neighbor_ip_list.append(session['addr'])
81+
82+
return bgp_neighbor_ip_list
83+
84+
85+
4686
# Returns string containing IP address of neighbor with hostname <hostname> or None if <hostname> not a neighbor
4787
def _get_neighbor_ipaddress_by_hostname(hostname):
48-
# Get BGP ASN from minigraph
88+
# Get BGP sessions from minigraph
4989
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-m', MINIGRAPH_PATH, '--var-json', MINIGRAPH_BGP_SESSIONS],
5090
stdout=subprocess.PIPE,
5191
shell=False,
@@ -56,22 +96,43 @@ def _get_neighbor_ipaddress_by_hostname(hostname):
5696

5797
for session in bgp_session_list:
5898
if session['name'] == hostname:
59-
return session['addr'];
99+
return session['addr']
60100

61101
return None
62102

103+
# Shut down BGP session by IP address and modify bgp_admin.yml accordingly
104+
def _bgp_session_shutdown(bgp_asn, ipaddress, verbose):
105+
click.echo("Shutting down BGP session with neighbor {}...".format(ipaddress))
63106

64-
# Run bash command and print output to stdout
65-
def run_command(command, pager=False):
66-
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
67-
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
68-
if pager is True:
69-
click.echo_via_pager(p.stdout.read())
70-
else:
71-
click.echo(p.stdout.read())
72-
p.wait()
73-
if p.returncode != 0:
74-
sys.exit(p.returncode)
107+
# Shut down the BGP session
108+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} shutdown'".format(bgp_asn, ipaddress)
109+
run_command(command, display_cmd=verbose)
110+
111+
if os.path.isfile(BGP_ADMIN_STATE_YML_PATH):
112+
# Remove existing item in bgp_admin.yml about the admin state of this neighbor
113+
command = "sed -i \"/^\s*{}:/d\" {}".format(ipaddress, BGP_ADMIN_STATE_YML_PATH)
114+
run_command(command, display_cmd=verbose)
115+
116+
# and add a new line mark it as off
117+
command = "echo \" {}: off\" >> {}".format(ipaddress, BGP_ADMIN_STATE_YML_PATH)
118+
run_command(command, display_cmd=verbose)
119+
120+
# Start up BGP session by IP address and modify bgp_admin.yml accordingly
121+
def _bgp_session_startup(bgp_asn, ipaddress, verbose):
122+
click.echo("Starting up BGP session with neighbor {}...".format(ipaddress))
123+
124+
# Start up the BGP session
125+
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {} shutdown'".format(bgp_asn, ipaddress)
126+
run_command(command, display_cmd=verbose)
127+
128+
if os.path.isfile(BGP_ADMIN_STATE_YML_PATH):
129+
# Remove existing item in bgp_admin.yml about the admin state of this neighbor
130+
command = "sed -i \"/^\s*{}:/d\" {}".format(ipaddress, BGP_ADMIN_STATE_YML_PATH)
131+
run_command(command, display_cmd=verbose)
132+
133+
# and add a new line mark it as on
134+
command = "echo \" {}: on\" >> {}".format(ipaddress, BGP_ADMIN_STATE_YML_PATH)
135+
run_command(command, display_cmd=verbose)
75136

76137

77138
# This is our main entrypoint - the main 'config' command
@@ -87,7 +148,7 @@ def cli():
87148

88149
@cli.group()
89150
def bgp():
90-
"""BGP-related tasks"""
151+
"""BGP-related configuration tasks"""
91152
pass
92153

93154
#
@@ -99,11 +160,23 @@ def shutdown():
99160
"""Shut down BGP session(s)"""
100161
pass
101162

163+
# 'all' subcommand
164+
@shutdown.command()
165+
@click.option('-v', '--verbose', is_flag=True, help="Enable verbose output")
166+
def all(verbose):
167+
"""Shut down all BGP sessions"""
168+
169+
bgp_asn = _get_bgp_asn_from_minigraph()
170+
bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses()
171+
172+
for ipaddress in bgp_neighbor_ip_list:
173+
_bgp_session_shutdown(bgp_asn, ipaddress, verbose)
102174

103175
# 'neighbor' subcommand
104176
@shutdown.command()
105-
@click.argument('ipaddr_or_hostname', required=True)
106-
def neighbor(ipaddr_or_hostname):
177+
@click.argument('ipaddr_or_hostname', metavar='<ipaddr_or_hostname>', required=True)
178+
@click.option('-v', '--verbose', is_flag=True, help="Enable verbose output")
179+
def neighbor(ipaddr_or_hostname, verbose):
107180
"""Shut down BGP session by neighbor IP address or hostname"""
108181
bgp_asn = _get_bgp_asn_from_minigraph()
109182

@@ -117,25 +190,30 @@ def neighbor(ipaddr_or_hostname):
117190
print "Error: could not locate neighbor '{}'".format(ipaddr_or_hostname)
118191
raise click.Abort
119192

120-
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} shutdown'".format(bgp_asn, ipaddress)
121-
run_command(command)
122-
# Remove existing item in bgp_admin.yml about the admin state of this neighbor
123-
command = 'sed -i "/^\s*{}:/d" /etc/sonic/bgp_admin.yml'.format(ipaddress)
124-
run_command(command)
125-
# and add a new line mark it as off
126-
command = 'echo " {}: off" >> /etc/sonic/bgp_admin.yml'.format(ipaddress)
127-
run_command(command)
193+
_bgp_session_shutdown(bgp_asn, ipaddress, verbose)
194+
128195

129196
@bgp.group()
130197
def startup():
131198
"""Start up BGP session(s)"""
132199
pass
133200

201+
# 'all' subcommand
202+
@startup.command()
203+
@click.option('-v', '--verbose', is_flag=True, help="Enable verbose output")
204+
def all(verbose):
205+
"""Start up all BGP sessions"""
206+
bgp_asn = _get_bgp_asn_from_minigraph()
207+
bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses()
208+
209+
for ipaddress in bgp_neighbor_ip_list:
210+
_bgp_session_startup(bgp_asn, ipaddress, verbose)
134211

135212
# 'neighbor' subcommand
136213
@startup.command()
137-
@click.argument('ipaddr_or_hostname', required=True)
138-
def neighbor(ipaddr_or_hostname):
214+
@click.argument('ipaddr_or_hostname', metavar='<ipaddr_or_hostname>', required=True)
215+
@click.option('-v', '--verbose', is_flag=True, help="Enable verbose output")
216+
def neighbor(ipaddr_or_hostname, verbose):
139217
"""Start up BGP session by neighbor IP address or hostname"""
140218
bgp_asn = _get_bgp_asn_from_minigraph()
141219

@@ -149,14 +227,7 @@ def neighbor(ipaddr_or_hostname):
149227
print "Error: could not locate neighbor '{}'".format(ipaddr_or_hostname)
150228
raise click.Abort
151229

152-
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {} shutdown'".format(bgp_asn, ipaddress)
153-
run_command(command)
154-
# Remove existing item in bgp_admin.yml about the admin state of this neighbor
155-
command = 'sed -i "/^\s*{}:/d" /etc/sonic/bgp_admin.yml'.format(ipaddress)
156-
run_command(command)
157-
# and add a new line mark it as on
158-
command = 'echo " {}: on" >> /etc/sonic/bgp_admin.yml'.format(ipaddress)
159-
run_command(command)
230+
_bgp_session_startup(bgp_asn, ipaddress, verbose)
160231

161232

162233
if __name__ == '__main__':

0 commit comments

Comments
 (0)