X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Fhoneycomb%2FBGP.py;h=37a9cb65586df55e88fe6c85c80115bc1320d444;hp=ca50cc31201d950d9497d8b504e19e02c7b1626f;hb=67f247b4015b76641c6fab7c49e7d9862043c856;hpb=5a02dd13563a5c67e336f04eb526cbea206da29b diff --git a/resources/libraries/python/honeycomb/BGP.py b/resources/libraries/python/honeycomb/BGP.py index ca50cc3120..37a9cb6558 100644 --- a/resources/libraries/python/honeycomb/BGP.py +++ b/resources/libraries/python/honeycomb/BGP.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Cisco and/or its affiliates. +# Copyright (c) 2018 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -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,8 +43,8 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not - 200 = OK or 201 = ACCEPTED. + :raises HoneycombError: If the status code in response to PUT is not + 200 = OK or 201 = ACCEPTED. """ if data is None: @@ -69,8 +71,8 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not - 200 = OK or 201 = ACCEPTED. + :raises HoneycombError: If the status code in response to PUT is not + 200 = OK or 201 = ACCEPTED. """ if data is None: @@ -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,86 @@ 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.")