Update bgpcfgd with vrf support (#3952)
* Implement path traversal just once * Add support of vrf to bgpcfgd
This commit is contained in:
parent
0dae59ac30
commit
122124679d
@ -120,29 +120,23 @@ class Directory(object):
|
|||||||
self.data = defaultdict(dict)
|
self.data = defaultdict(dict)
|
||||||
self.notify = defaultdict(lambda: defaultdict(list))
|
self.notify = defaultdict(lambda: defaultdict(list))
|
||||||
|
|
||||||
def path_exist(self, slot, path):
|
def path_traverse(self, slot, path):
|
||||||
if slot not in self.data:
|
if slot not in self.data:
|
||||||
return False
|
return False, None
|
||||||
elif path == '':
|
elif path == '':
|
||||||
return True
|
return True, self.data[slot]
|
||||||
d = self.data[slot]
|
d = self.data[slot]
|
||||||
for p in path.split("/"):
|
for p in path.split("/"):
|
||||||
if p not in d:
|
if p not in d:
|
||||||
return False
|
return False, None
|
||||||
d = d[p]
|
d = d[p]
|
||||||
return True
|
return True, d
|
||||||
|
|
||||||
|
def path_exist(self, slot, path):
|
||||||
|
return self.path_traverse(slot, path)[0]
|
||||||
|
|
||||||
def get_path(self, slot, path):
|
def get_path(self, slot, path):
|
||||||
if slot not in self.data:
|
return self.path_traverse(slot, path)[1]
|
||||||
return None
|
|
||||||
elif path == '':
|
|
||||||
return self.data[slot]
|
|
||||||
d = self.data[slot]
|
|
||||||
for p in path.split("/"):
|
|
||||||
if p not in d:
|
|
||||||
return None
|
|
||||||
d = d[p]
|
|
||||||
return d
|
|
||||||
|
|
||||||
def put(self, slot, key, value):
|
def put(self, slot, key, value):
|
||||||
self.data[slot][key] = value
|
self.data[slot][key] = value
|
||||||
@ -289,6 +283,8 @@ class BGPPeerMgr(Manager):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def set_handler(self, key, data):
|
def set_handler(self, key, data):
|
||||||
|
key = self.normalize_key(key)
|
||||||
|
vrf, nbr = key.split('|', 1)
|
||||||
if key not in self.peers:
|
if key not in self.peers:
|
||||||
cmd = None
|
cmd = None
|
||||||
neigmeta = self.directory.get_slot("neigmeta")
|
neigmeta = self.directory.get_slot("neigmeta")
|
||||||
@ -298,14 +294,14 @@ class BGPPeerMgr(Manager):
|
|||||||
cmd = self.templates["add"].render(
|
cmd = self.templates["add"].render(
|
||||||
DEVICE_METADATA=self.directory.get_slot("meta"),
|
DEVICE_METADATA=self.directory.get_slot("meta"),
|
||||||
DEVICE_NEIGHBOR_METADATA=neigmeta,
|
DEVICE_NEIGHBOR_METADATA=neigmeta,
|
||||||
neighbor_addr=key,
|
neighbor_addr=nbr,
|
||||||
bgp_session=data
|
bgp_session=data
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
syslog.syslog(syslog.LOG_ERR, 'Peer {}. Error in rendering the template for "SET" command {}'.format(key, data))
|
syslog.syslog(syslog.LOG_ERR, 'Peer {}. Error in rendering the template for "SET" command {}'.format(key, data))
|
||||||
return True
|
return True
|
||||||
if cmd is not None:
|
if cmd is not None:
|
||||||
rc = self.apply_op(cmd)
|
rc = self.apply_op(cmd, vrf)
|
||||||
if rc:
|
if rc:
|
||||||
self.peers.add(key)
|
self.peers.add(key)
|
||||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} added with attributes {}'.format(key, data))
|
syslog.syslog(syslog.LOG_INFO, 'Peer {} added with attributes {}'.format(key, data))
|
||||||
@ -316,13 +312,13 @@ class BGPPeerMgr(Manager):
|
|||||||
# commands for the peers only
|
# commands for the peers only
|
||||||
if "admin_status" in data:
|
if "admin_status" in data:
|
||||||
if data['admin_status'] == 'up':
|
if data['admin_status'] == 'up':
|
||||||
rc = self.apply_op(self.templates["no shutdown"].render(neighbor_addr=key))
|
rc = self.apply_op(self.templates["no shutdown"].render(neighbor_addr=nbr), vrf)
|
||||||
if rc:
|
if rc:
|
||||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "up"'.format(key))
|
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "up"'.format(key))
|
||||||
else:
|
else:
|
||||||
syslog.syslog(syslog.LOG_ERR, "Peer {} admin state wasn't set to 'up'.".format(key))
|
syslog.syslog(syslog.LOG_ERR, "Peer {} admin state wasn't set to 'up'.".format(key))
|
||||||
elif data['admin_status'] == 'down':
|
elif data['admin_status'] == 'down':
|
||||||
rc = self.apply_op(self.templates["shutdown"].render(neighbor_addr=key))
|
rc = self.apply_op(self.templates["shutdown"].render(neighbor_addr=nbr), vrf)
|
||||||
if rc:
|
if rc:
|
||||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "down"'.format(key))
|
syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "down"'.format(key))
|
||||||
else:
|
else:
|
||||||
@ -334,23 +330,28 @@ class BGPPeerMgr(Manager):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def del_handler(self, key):
|
def del_handler(self, key):
|
||||||
|
key = self.normalize_key(key)
|
||||||
|
vrf, nbr = key.split('|', 1)
|
||||||
if key not in self.peers:
|
if key not in self.peers:
|
||||||
syslog.syslog(syslog.LOG_WARNING, 'Peer {} has not been found'.format(key))
|
syslog.syslog(syslog.LOG_WARNING, 'Peer {} has not been found'.format(key))
|
||||||
return
|
return
|
||||||
cmd = self.templates["delete"].render(neighbor_addr=key)
|
cmd = self.templates["delete"].render(neighbor_addr=nbr)
|
||||||
rc = self.apply_op(cmd)
|
rc = self.apply_op(cmd, vrf)
|
||||||
if rc:
|
if rc:
|
||||||
syslog.syslog(syslog.LOG_INFO, 'Peer {} has been removed'.format(key))
|
syslog.syslog(syslog.LOG_INFO, 'Peer {} has been removed'.format(key))
|
||||||
self.peers.remove(key)
|
self.peers.remove(key)
|
||||||
else:
|
else:
|
||||||
syslog.syslog(syslog.LOG_ERR, "Peer {} hasn't been removed".format(key))
|
syslog.syslog(syslog.LOG_ERR, "Peer {} hasn't been removed".format(key))
|
||||||
|
|
||||||
def apply_op(self, cmd):
|
def apply_op(self, cmd, vrf):
|
||||||
bgp_asn = self.directory.get_slot("meta")["localhost"]["bgp_asn"]
|
bgp_asn = self.directory.get_slot("meta")["localhost"]["bgp_asn"]
|
||||||
fd, tmp_filename = tempfile.mkstemp(dir='/tmp')
|
fd, tmp_filename = tempfile.mkstemp(dir='/tmp')
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
with open(tmp_filename, 'w') as fp:
|
with open(tmp_filename, 'w') as fp:
|
||||||
|
if vrf == 'default':
|
||||||
fp.write('router bgp %s\n' % bgp_asn)
|
fp.write('router bgp %s\n' % bgp_asn)
|
||||||
|
else:
|
||||||
|
fp.write('router bgp %s vrf %s\n' % (bgp_asn, vrf))
|
||||||
fp.write("%s\n" % cmd)
|
fp.write("%s\n" % cmd)
|
||||||
|
|
||||||
command = ["vtysh", "-f", tmp_filename]
|
command = ["vtysh", "-f", tmp_filename]
|
||||||
@ -358,14 +359,31 @@ class BGPPeerMgr(Manager):
|
|||||||
os.remove(tmp_filename)
|
os.remove(tmp_filename)
|
||||||
return rc == 0
|
return rc == 0
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def normalize_key(key):
|
||||||
|
if '|' not in key:
|
||||||
|
return 'default|' + key
|
||||||
|
else:
|
||||||
|
return key
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_peers():
|
def load_peers():
|
||||||
|
vrfs = []
|
||||||
|
command = ["vtysh", "-c", "show bgp vrfs json"]
|
||||||
|
rc, out, err = run_command(command)
|
||||||
|
if rc == 0:
|
||||||
|
js_vrf = json.loads(out)
|
||||||
|
vrfs = js_vrf['vrfs'].keys()
|
||||||
|
|
||||||
peers = set()
|
peers = set()
|
||||||
command = ["vtysh", "-c", "show bgp neighbors json"]
|
for vrf in vrfs:
|
||||||
|
command = ["vtysh", "-c", 'show bgp vrf {} neighbors json'.format(vrf)]
|
||||||
rc, out, err = run_command(command)
|
rc, out, err = run_command(command)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
js_bgp = json.loads(out)
|
js_bgp = json.loads(out)
|
||||||
peers = set(js_bgp.keys())
|
for nbr in js_bgp.keys():
|
||||||
|
peers.add((vrf, nbr))
|
||||||
|
|
||||||
return peers
|
return peers
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user