diff options
Diffstat (limited to 'resources/libraries/python/honeycomb/BGP.py')
-rw-r--r-- | resources/libraries/python/honeycomb/BGP.py | 107 |
1 files changed, 100 insertions, 7 deletions
diff --git a/resources/libraries/python/honeycomb/BGP.py b/resources/libraries/python/honeycomb/BGP.py index ca50cc3120..75dce762ff 100644 --- a/resources/libraries/python/honeycomb/BGP.py +++ b/resources/libraries/python/honeycomb/BGP.py @@ -13,6 +13,7 @@ """Keywords to manipulate BGP configuration using Honeycomb REST API.""" +from resources.libraries.python.constants import Constants as Const from resources.libraries.python.HTTPRequest import HTTPCodes from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError from resources.libraries.python.honeycomb.HoneycombUtil \ @@ -27,6 +28,7 @@ class BGPKeywords(object): """ def __init__(self): + """Initializer.""" pass @staticmethod @@ -41,7 +43,7 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not + :raises HoneycombError: If the status code in response to PUT is not 200 = OK or 201 = ACCEPTED. """ @@ -69,7 +71,7 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not + :raises HoneycombError: If the status code in response to PUT is not 200 = OK or 201 = ACCEPTED. """ @@ -93,6 +95,7 @@ class BGPKeywords(object): :type node: dict :returns: BGP configuration data. :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. """ status_code, resp = HcUtil. \ @@ -104,21 +107,29 @@ class BGPKeywords(object): return resp @staticmethod - def get_bgp_peer(node, address): + def get_bgp_peer(node, address, datastore='config'): """Get BGP configuration of the specified peer from the node. :param node: Honeycomb node. :param address: IP address of the peer. + :param datastore: Get data from config or operational datastore. :type node: dict :type address: str + :type datastore; str :returns: BGP peer configuration data. :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. """ path = "bgp-openconfig-extensions:neighbors/" \ "neighbor/{0}".format(address) + if datastore != "operational": + url = "config_bgp_peer" + else: + url = "oper_bgp" + path = "peer/bgp:%2F%2F{0}".format(address) status_code, resp = HcUtil. \ - get_honeycomb_data(node, "config_bgp_peer", path) + get_honeycomb_data(node, url, path) if status_code != HTTPCodes.OK: raise HoneycombError( "Not possible to get configuration information about the BGP" @@ -211,7 +222,7 @@ class BGPKeywords(object): :type ip_version: str :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the operation fails. + :raises HoneycombError: If the status code in response is not 200 = OK. """ route_address = route_address.replace("/", "%2F") @@ -239,7 +250,7 @@ class BGPKeywords(object): def get_all_peer_routes(node, peer_address, ip_version): """Get all configured routes for the given BGP peer. - :param node: HOneycomb node. + :param node: Honeycomb node. :param peer_address: IP address of the peer. :param ip_version: IP protocol version. ipv4 or ipv6 :type node: dict @@ -247,7 +258,7 @@ class BGPKeywords(object): :type ip_version: str :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the operation fails. + :raises HoneycombError: If the status code in response is not 200 = OK. """ if ip_version.lower() == "ipv4": @@ -299,3 +310,85 @@ class BGPKeywords(object): .format(peer_address, route_address, index) return BGPKeywords._configure_bgp_route(node, path) + + @staticmethod + def get_bgp_local_rib(node): + """Get local RIB table from the Honeycomb node. + + :param node: Honeycomb node. + :type node: dict + :returns: RIB operational data. + :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. + """ + + path = "loc-rib" + + status_code, resp = HcUtil. \ + get_honeycomb_data(node, "oper_bgp", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational data from BGP local RIB." + " Status code: {0}.".format(status_code)) + + return resp + + @staticmethod + def configure_bgp_base(node, ip_address, port, as_number): + """Modify BGP config file. Requires a restart of Honeycomb to take + effect. + + :param node: Honeycomb node. + :param ip_address: BGP peer identifier/binding address. + :param port: BGP binding port. + :param as_number: Autonomous System ID number. + :type node: dict + :type ip_address: str + :type port: int + :type as_number: int + :raises HoneycombError: If modifying the configuration fails. + """ + + from resources.libraries.python.ssh import SSH + + config = { + '\\"bgp-binding-address\\"': '\\"{0}\\"'.format(ip_address), + '\\"bgp-port\\"': port, + '\\"bgp-as-number\\"': as_number} + + path = "{0}/config/bgp.json".format(Const.REMOTE_HC_DIR) + + for key, value in config.items(): + find = key + replace = '"{0}": "{1}",'.format(key, value) + + argument = '"/{0}/c\\ {1}"'.format(find, replace) + command = "sed -i {0} {1}".format(argument, path) + + ssh = SSH() + ssh.connect(node) + (ret_code, _, stderr) = ssh.exec_command_sudo(command) + if ret_code != 0: + raise HoneycombError("Failed to modify configuration on " + "node {0}, {1}".format(node, stderr)) + + @staticmethod + def compare_rib_tables(data, ref): + """Compare provided RIB table with reference. All reference entries must + be present in data. Data entries not present in reference are ignored. + + :param data: Data from Honeycomb node. + :param ref: Reference data to compare against. + :type data: dict + :type ref: dict + :raises HoneycombError: If the tables do not match.""" + + # Remove runtime attributes from data + for item in data: + item.pop("attributes", "") + + for item in ref: + if item not in data: + raise HoneycombError( + "RIB entry {0} not found in operational data.") |