aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python
diff options
context:
space:
mode:
authorselias <samelias@cisco.com>2017-10-09 16:36:16 +0200
committerTibor Frank <tifrank@cisco.com>2017-11-08 13:26:45 +0000
commit56dd61dee872da788e578129eed48a3158a5b566 (patch)
tree4f56e96f06f78a8180c800eceabc56ce7046b4f5 /resources/libraries/python
parent2b8547bc50fd06ea936f096794b8c2a5e09c5f8b (diff)
CSIT-811 HC Test: BGP functional tests
Added traffic tests for Honeycomb's BGP feature. Change-Id: I5fa99908ab61d8bc9d2975e451917b98571b6aca Signed-off-by: selias <samelias@cisco.com>
Diffstat (limited to 'resources/libraries/python')
-rw-r--r--resources/libraries/python/honeycomb/BGP.py107
-rw-r--r--resources/libraries/python/honeycomb/HoneycombSetup.py32
2 files changed, 128 insertions, 11 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.")
diff --git a/resources/libraries/python/honeycomb/HoneycombSetup.py b/resources/libraries/python/honeycomb/HoneycombSetup.py
index 7c3831ca04..d4175b13e4 100644
--- a/resources/libraries/python/honeycomb/HoneycombSetup.py
+++ b/resources/libraries/python/honeycomb/HoneycombSetup.py
@@ -61,12 +61,13 @@ class HoneycombSetup(object):
HoneycombSetup.print_environment(nodes)
- logger.console("\n(re)Starting Honeycomb service ...")
-
cmd = "sudo service honeycomb start"
for node in nodes:
if node['type'] == NodeType.DUT:
+ logger.console(
+ "\n(re)Starting Honeycomb service on node {0}".format(
+ node["host"]))
ssh = SSH()
ssh.connect(node)
(ret_code, _, _) = ssh.exec_command_sudo(cmd)
@@ -89,13 +90,15 @@ class HoneycombSetup(object):
:type nodes: list
:raises HoneycombError: If Honeycomb failed to stop.
"""
- logger.console("\nShutting down Honeycomb service ...")
cmd = "sudo service honeycomb stop"
errors = []
for node in nodes:
if node['type'] == NodeType.DUT:
+ logger.console(
+ "\nShutting down Honeycomb service on node {0}".format(
+ node["host"]))
ssh = SSH()
ssh.connect(node)
(ret_code, _, _) = ssh.exec_command_sudo(cmd)
@@ -121,7 +124,8 @@ class HoneycombSetup(object):
:raises HoneycombError: If Honeycomb fails to start.
"""
- logger.console("\n(re)Starting Honeycomb service ...")
+ logger.console(
+ "\n(re)Starting Honeycomb service on node {0}".format(node["host"]))
cmd = "sudo service honeycomb restart"
@@ -650,6 +654,26 @@ class HoneycombSetup(object):
logger.info("ODL client service stopped.")
+ @staticmethod
+ def set_static_arp(node, ip_address, mac_address):
+ """Configure a static ARP entry using arp.
+
+ :param node: Node in topology.
+ :param ip_address: IP address for the entry.
+ :param mac_address: MAC adddress for the entry.
+ :type node: dict
+ :type ip_address: str
+ :type mac_address: str
+ :raises RuntimeError: If the operation fails.
+ """
+
+ ssh = SSH()
+ ssh.connect(node)
+ ret_code, _, _ = ssh.exec_command_sudo("arp -s {0} {1}".format(
+ ip_address, mac_address))
+
+ if ret_code != 0:
+ raise RuntimeError("Failed to configure static ARP adddress.")
class HoneycombStartupConfig(object):