aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python
diff options
context:
space:
mode:
authorTibor Frank <tifrank@cisco.com>2016-04-28 15:44:25 +0200
committerMatej Klotton <mklotton@cisco.com>2016-05-06 14:57:37 +0000
commit07c0ae2e49665961af4a8b9734218e9c5f8cd3ca (patch)
tree7b8812a31aa56bb2cade01fa7b49428c85db522c /resources/libraries/python
parent2e6b88e7c414e31336fd6644143b257e94b89624 (diff)
Honeycomb API keywords - interface, bridge domain
- add keywords to manipulate data using Honeycomb REST API to configure interfaces and bridge domains - remove "add_vpp_to_honeycomb_network_topology" method from HoneycombSetup.py - remove "parse_json_response" from HoneycombUtil.py - add methods to manipulate data from Honeycomb REST API Change-Id: I5e6f87097fe9bfccffa3d4aae21f63281353cf29 Signed-off-by: Tibor Frank <tifrank@cisco.com>
Diffstat (limited to 'resources/libraries/python')
-rw-r--r--resources/libraries/python/HcAPIKwBridgeDomain.py329
-rw-r--r--resources/libraries/python/HcAPIKwInterfaces.py712
-rw-r--r--resources/libraries/python/HoneycombAPIKeywords.py543
-rw-r--r--resources/libraries/python/HoneycombSetup.py92
-rw-r--r--resources/libraries/python/HoneycombUtil.py183
5 files changed, 1186 insertions, 673 deletions
diff --git a/resources/libraries/python/HcAPIKwBridgeDomain.py b/resources/libraries/python/HcAPIKwBridgeDomain.py
new file mode 100644
index 0000000000..2f7c149684
--- /dev/null
+++ b/resources/libraries/python/HcAPIKwBridgeDomain.py
@@ -0,0 +1,329 @@
+# Copyright (c) 2016 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:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Keywords to manipulate bridge domain configuration using Honeycomb REST API.
+
+The keywords make possible to put and get configuration data and to get
+operational data.
+"""
+
+
+from resources.libraries.python.HTTPRequest import HTTPCodes
+from resources.libraries.python.HoneycombSetup import HoneycombError
+from resources.libraries.python.HoneycombUtil import HoneycombUtil as HcUtil
+from resources.libraries.python.HoneycombUtil import DataRepresentation
+
+
+class BridgeDomainKeywords(object):
+ """Keywords to manipulate bridge domain configuration.
+
+ Implements keywords which get configuration and operational data about
+ bridge domains and put the bridge domains' parameters using Honeycomb REST
+ API.
+ """
+
+ PARAMS = ("flood", "forward", "learn", "unknown-unicast-flood",
+ "arp-termination")
+
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def _configure_bd(node, bd_name, data,
+ data_representation=DataRepresentation.JSON):
+ """Send bridge domain configuration data and check the response.
+
+ :param node: Honeycomb node.
+ :param bd_name: The name of bridge domain.
+ :param data: Configuration data to be sent in PUT request.
+ :param data_representation: How the data is represented.
+ :type node: dict
+ :type bd_name: str
+ :type data: dict
+ :type data_representation: DataRepresentation
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the status code in response on PUT is not
+ 200 = OK.
+ """
+
+ status_code, resp = HcUtil.\
+ put_honeycomb_data(node, "config_bridge_domain", data,
+ data_representation=data_representation)
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "The configuration of bridge domain '{0}' was not successful. "
+ "Status code: {1}.".format(bd_name, status_code))
+ return resp
+
+ @staticmethod
+ def _set_bd_properties(node, bd_name, path, new_value=None):
+ """Set bridge domain properties.
+
+ This method reads bridge domain configuration data, creates, changes or
+ removes the requested data and puts it back to Honeycomb.
+
+ :param node: Honeycomb node.
+ :param bd_name: The name of bridge domain.
+ :param path: Path to data we want to change, create or remove.
+ :param new_value: The new value to be set. If None, the item will be
+ removed.
+ :type node: dict
+ :type bd_name: str
+ :type path: tuple
+ :type new_value: str, dict or list
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If it is not possible to get or set the data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "config_bridge_domain")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get configuration information about the "
+ "bridge domains. Status code: {0}.".format(status_code))
+
+ if new_value:
+ new_data = HcUtil.set_item_value(resp, path, new_value)
+ else:
+ new_data = HcUtil.remove_item(resp, path)
+ return BridgeDomainKeywords._configure_bd(node, bd_name, new_data)
+
+ @staticmethod
+ def _create_bd_structure(bd_name, **kwargs):
+ """Create the bridge domain data structure as it is expected by
+ Honeycomb REST API.
+
+ :param bd_name: Bridge domain name.
+ :param kwargs: Parameters and their values. The accepted parameters are
+ defined in BridgeDomainKeywords.PARAMS.
+ :type bd_name: str
+ :type kwargs: dict
+ :return: Bridge domain data structure.
+ :rtype: dict
+ """
+
+ bd_structure = {"name": bd_name}
+
+ for param, value in kwargs.items():
+ if param not in BridgeDomainKeywords.PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".
+ format(param))
+ bd_structure[param] = str(value)
+
+ return bd_structure
+
+ @staticmethod
+ def get_all_bds_cfg_data(node):
+ """Get configuration data about all bridge domains from Honeycomb.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :return: Configuration data about all bridge domains from Honeycomb.
+ :rtype: list
+ :raises HoneycombError: If it is not possible to get configuration data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "config_bridge_domain")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get configuration information about the "
+ "bridge domains. Status code: {0}.".format(status_code))
+ try:
+ return resp["bridge-domains"]["bridge-domain"]
+
+ except (KeyError, TypeError):
+ return []
+
+ @staticmethod
+ def get_bd_cfg_data(node, bd_name):
+ """Get configuration data about the given bridge domain from Honeycomb.
+
+ :param node: Honeycomb node.
+ :param bd_name: The name of bridge domain.
+ :type node: dict
+ :type bd_name: str
+ :return: Configuration data about the given bridge domain from
+ Honeycomb.
+ :rtype: dict
+ """
+
+ intfs = BridgeDomainKeywords.get_all_bds_cfg_data(node)
+ for intf in intfs:
+ if intf["name"] == bd_name:
+ return intf
+ return {}
+
+ @staticmethod
+ def get_all_bds_oper_data(node):
+ """Get operational data about all bridge domains from Honeycomb.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :return: Operational data about all bridge domains from Honeycomb.
+ :rtype: list
+ :raises HoneycombError: If it is not possible to get operational data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "oper_bridge_domains")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get operational information about the "
+ "bridge domains. Status code: {0}.".format(status_code))
+ try:
+ return resp["bridge-domains"]["bridge-domain"]
+
+ except (KeyError, TypeError):
+ return []
+
+ @staticmethod
+ def get_bd_oper_data(node, bd_name):
+ """Get operational data about the given bridge domain from Honeycomb.
+
+ :param node: Honeycomb node.
+ :param bd_name: The name of bridge domain.
+ :type node: dict
+ :type bd_name: str
+ :return: Operational data about the given bridge domain from Honeycomb.
+ :rtype: dict
+ """
+
+ intfs = BridgeDomainKeywords.get_all_bds_oper_data(node)
+ for intf in intfs:
+ if intf["name"] == bd_name:
+ return intf
+ return {}
+
+ @staticmethod
+ def add_first_bd(node, bd_name, **kwargs):
+ """Add the first bridge domain.
+
+ If there are any other bridge domains configured, they will be removed.
+
+ :param node: Honeycomb node.
+ :param bd_name: Bridge domain name.
+ :param kwargs: Parameters and their values. The accepted parameters are
+ defined in BridgeDomainKeywords.PARAMS
+ :type node: dict
+ :type bd_name: str
+ :type kwargs: dict
+ :return: Bridge domain data structure.
+ :rtype: dict
+ """
+
+ path = ("bridge-domains", )
+ new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
+ bridge_domain = {"bridge-domain": [new_bd, ]}
+ return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
+ bridge_domain)
+
+ @staticmethod
+ def add_bd(node, bd_name, **kwargs):
+ """Add a bridge domain.
+
+ :param node: Honeycomb node.
+ :param bd_name: Bridge domain name.
+ :param kwargs: Parameters and their values. The accepted parameters are
+ defined in BridgeDomainKeywords.PARAMS
+ :type node: dict
+ :type bd_name: str
+ :type kwargs: dict
+ :return: Bridge domain data structure.
+ :rtype: dict
+ """
+
+ path = ("bridge-domains", "bridge-domain")
+ new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
+ bridge_domain = [new_bd, ]
+ return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
+ bridge_domain)
+
+ @staticmethod
+ def remove_all_bds(node):
+ """Remove all bridge domains.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If it is not possible to remove all bridge
+ domains.
+ """
+
+ data = {"bridge-domains": {"bridge-domain": []}}
+ status_code, resp = HcUtil.\
+ put_honeycomb_data(node, "config_bridge_domain", data)
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError("Not possible to remove all bridge domains. "
+ "Status code: {0}.".format(status_code))
+ return resp
+
+ @staticmethod
+ def remove_bridge_domain(node, bd_name):
+ """Remove a bridge domain.
+
+ :param node: Honeycomb node.
+ :param bd_name: The name of bridge domain to be removed.
+ :type node: dict
+ :type bd_name: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError:If it is not possible to remove the bridge
+ domain.
+ """
+
+ path = ("bridge-domains", ("bridge-domain", "name", bd_name))
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "config_bridge_domain")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get configuration information about the "
+ "bridge domains. Status code: {0}.".format(status_code))
+
+ new_data = HcUtil.remove_item(resp, path)
+ status_code, resp = HcUtil.\
+ put_honeycomb_data(node, "config_bridge_domain", new_data)
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError("Not possible to remove bridge domain {0}. "
+ "Status code: {1}.".
+ format(bd_name, status_code))
+ return resp
+
+ @staticmethod
+ def configure_bridge_domain(node, bd_name, param, value):
+ """Configure a bridge domain.
+
+ :param node: Honeycomb node.
+ :param bd_name: Bridge domain name.
+ :param param: Parameter to set, change or remove. The accepted
+ parameters are defined in BridgeDomainKeywords.PARAMS
+ :param value: The new value to be set, change or remove. If None, the
+ item will be removed.
+ :type node: dict
+ :type bd_name: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ if param not in BridgeDomainKeywords.PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ path = ("bridge-domains", ("bridge-domain", "name", bd_name), param)
+ return BridgeDomainKeywords.\
+ _set_bd_properties(node, bd_name, path, value)
diff --git a/resources/libraries/python/HcAPIKwInterfaces.py b/resources/libraries/python/HcAPIKwInterfaces.py
new file mode 100644
index 0000000000..ccdb5ddefd
--- /dev/null
+++ b/resources/libraries/python/HcAPIKwInterfaces.py
@@ -0,0 +1,712 @@
+# Copyright (c) 2016 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:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Keywords to manipulate interface configuration using Honeycomb REST API.
+
+The keywords make possible to put and get configuration data and to get
+operational data.
+"""
+
+
+from resources.libraries.python.HTTPRequest import HTTPCodes
+from resources.libraries.python.HoneycombSetup import HoneycombError
+from resources.libraries.python.HoneycombUtil import HoneycombUtil as HcUtil
+from resources.libraries.python.HoneycombUtil import DataRepresentation
+
+
+class InterfaceKeywords(object):
+ """Keywords for Interface manipulation.
+
+ Implements keywords which get configuration and operational data about
+ vpp interfaces and set the interface's parameters using Honeycomb REST API.
+ """
+
+ INTF_PARAMS = ("name", "description", "type", "enabled",
+ "link-up-down-trap-enable")
+ IPV4_PARAMS = ("enabled", "forwarding", "mtu")
+ IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
+ IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
+ "create-temporary-addresses",
+ "temporary-valid-lifetime",
+ "temporary-preferred-lifetime")
+ ETH_PARAMS = ("mtu", )
+ ROUTING_PARAMS = ("vrf-id", )
+ VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
+ L2_PARAMS = ("bridge-domain", "split-horizon-group",
+ "bridged-virtual-interface")
+
+ def __init__(self):
+ pass
+
+ @staticmethod
+ def _configure_interface(node, interface, data,
+ data_representation=DataRepresentation.JSON):
+ """Send interface configuration data and check the response.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param data: Configuration data to be sent in PUT request.
+ :param data_representation: How the data is represented.
+ :type node: dict
+ :type interface: str
+ :type data: dict
+ :type data_representation: DataRepresentation
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the status code in response on PUT is not
+ 200 = OK.
+ """
+
+ status_code, resp = HcUtil.\
+ put_honeycomb_data(node, "config_vpp_interfaces", data,
+ data_representation=data_representation)
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "The configuration of interface '{0}' was not successful. "
+ "Status code: {1}.".format(interface, status_code))
+ return resp
+
+ @staticmethod
+ def get_all_interfaces_cfg_data(node):
+ """Get configuration data about all interfaces from Honeycomb.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :return: Configuration data about all interfaces from Honeycomb.
+ :rtype: list
+ :raises HoneycombError: If it is not possible to get configuration data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "config_vpp_interfaces")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get configuration information about the "
+ "interfaces. Status code: {0}.".format(status_code))
+ try:
+ return resp["interfaces"]["interface"]
+
+ except (KeyError, TypeError):
+ return []
+
+ @staticmethod
+ def get_interface_cfg_data(node, interface):
+ """Get configuration data about the given interface from Honeycomb.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Configuration data about the given interface from Honeycomb.
+ :rtype: dict
+ """
+
+ intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
+ for intf in intfs:
+ if intf["name"] == interface:
+ return intf
+ return {}
+
+ @staticmethod
+ def get_all_interfaces_oper_data(node):
+ """Get operational data about all interfaces from Honeycomb.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :return: Operational data about all interfaces from Honeycomb.
+ :rtype: list
+ :raises HoneycombError: If it is not possible to get operational data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "oper_vpp_interfaces")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get operational information about the "
+ "interfaces. Status code: {0}.".format(status_code))
+ try:
+ return resp["interfaces-state"]["interface"]
+
+ except (KeyError, TypeError):
+ return []
+
+ @staticmethod
+ def get_interface_oper_data(node, interface):
+ """Get operational data about the given interface from Honeycomb.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Operational data about the given interface from Honeycomb.
+ :rtype: dict
+ """
+
+ intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
+ for intf in intfs:
+ if intf["name"] == interface:
+ return intf
+ return {}
+
+ @staticmethod
+ def _set_interface_properties(node, interface, path, new_value=None):
+ """Set interface properties.
+
+ This method reads interface configuration data, creates, changes or
+ removes the requested data and puts it back to Honeycomb.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param path: Path to data we want to change / create / remove.
+ :param new_value: The new value to be set. If None, the item will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type path: tuple
+ :type new_value: str, dict or list
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If it is not possible to get or set the data.
+ """
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "config_vpp_interfaces")
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get configuration information about the "
+ "interfaces. Status code: {0}.".format(status_code))
+
+ if new_value:
+ new_data = HcUtil.set_item_value(resp, path, new_value)
+ else:
+ new_data = HcUtil.remove_item(resp, path)
+ return InterfaceKeywords._configure_interface(node, interface, new_data)
+
+ @staticmethod
+ def set_interface_state(node, interface, state="up"):
+ """Set VPP interface state.
+
+ The keyword changes the administration state of interface to up or down
+ depending on the parameter "state".
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param state: The requested state, only "up" and "down" are valid
+ values.
+ :type node: dict
+ :type interface: str
+ :type state: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises KeyError: If the argument "state" is nor "up" or "down".
+ :raises HoneycombError: If the interface is not present on the node.
+ """
+
+ intf_state = {"up": "true",
+ "down": "false"}
+
+ path = ("interfaces", ("interface", "name", str(interface)), "enabled")
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, intf_state[state.lower()])
+
+ @staticmethod
+ def set_interface_up(node, interface):
+ """Set the administration state of VPP interface to up.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response
+ :rtype: bytearray
+ """
+
+ return InterfaceKeywords.set_interface_state(node, interface, "up")
+
+ @staticmethod
+ def set_interface_down(node, interface):
+ """Set the administration state of VPP interface to down.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ return InterfaceKeywords.set_interface_state(node, interface, "down")
+
+ @staticmethod
+ def add_bridge_domain_to_interface(node, interface, bd_name,
+ split_horizon_group=None, bvi=None):
+ """Add a new bridge domain to an interface and set its parameters.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param bd_name: Bridge domain name.
+ :param split_horizon_group: Split-horizon group name.
+ :param bvi: The bridged virtual interface.
+ :type node: dict
+ :type interface: str
+ :type bd_name: str
+ :type split_horizon_group: str
+ :type bvi: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the interface is not present on the node.
+ """
+
+ v3po_l2 = {"bridge-domain": str(bd_name)}
+ if split_horizon_group:
+ v3po_l2["split-horizon-group"] = str(split_horizon_group)
+ if bvi:
+ v3po_l2["bridged-virtual-interface"] = str(bvi)
+
+ path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
+
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, v3po_l2)
+
+ @staticmethod
+ def configure_interface_base(node, interface, param, value):
+ """Configure the base parameters of interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.INTF_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ path = ("interfaces", ("interface", "name", interface), param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def configure_interface_ipv4(node, interface, param, value):
+ """Configure IPv4 parameters of interface
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.IPV4_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ path = ("interfaces", ("interface", "name", interface),
+ "ietf-ip:ipv4", param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def add_first_ipv4_address(node, interface, ip_addr, netmask):
+ """Add the first IPv4 address.
+
+ If there are any other addresses configured, they will be removed.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv4 address to be set.
+ :param netmask: Netmask.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type netmask: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
+ address = {"address": [{"ip": ip_addr, "netmask": netmask}, ]}
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, address)
+
+ @staticmethod
+ def add_ipv4_address(node, interface, ip_addr, netmask):
+ """Add IPv4 address.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv4 address to be set.
+ :param netmask: Netmask.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type netmask: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
+ "address")
+ address = [{"ip": ip_addr, "prefix-length": netmask}, ]
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, address)
+
+ @staticmethod
+ def remove_all_ipv4_addresses(node, interface):
+ """Remove all IPv4 addresses from interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
+ "address")
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, None)
+
+ @staticmethod
+ def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
+ """Add the first IPv4 neighbour.
+
+ If there are any other neighbours configured, they will be removed.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv4 address of neighbour to be set.
+ :param link_layer_address: Link layer address.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type link_layer_address: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
+ neighbor = {"neighbor": [{"ip": ip_addr,
+ "link-layer-address": link_layer_address}, ]}
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, neighbor)
+
+ @staticmethod
+ def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
+ """Add the IPv4 neighbour.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv4 address of neighbour to be set.
+ :param link_layer_address: Link layer address.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type link_layer_address: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
+ "neighbor")
+ neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, neighbor)
+
+ @staticmethod
+ def remove_all_ipv4_neighbors(node, interface):
+ """Remove all IPv4 neighbours.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
+ "neighbor")
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, None)
+
+ @staticmethod
+ def configure_interface_ipv6(node, interface, param, value):
+ """Configure IPv6 parameters of interface
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param in InterfaceKeywords.IPV6_PARAMS:
+ path = ("interfaces", ("interface", "name", interface),
+ "ietf-ip:ipv6", param)
+ elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
+ path = ("interfaces", ("interface", "name", interface),
+ "ietf-ip:ipv6", "autoconf", param)
+ else:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
+ """Add the first IPv6 address.
+
+ If there are any other addresses configured, they will be removed.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv6 address to be set.
+ :param prefix_len: Prefix length.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type prefix_len: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
+ address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, address)
+
+ @staticmethod
+ def add_ipv6_address(node, interface, ip_addr, prefix_len):
+ """Add IPv6 address.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv6 address to be set.
+ :param prefix_len: Prefix length.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type prefix_len: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
+ "address")
+ address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, address)
+
+ @staticmethod
+ def remove_all_ipv6_addresses(node, interface):
+ """Remove all IPv6 addresses from interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
+ "address")
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, None)
+
+ @staticmethod
+ def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
+ """Add the first IPv6 neighbour.
+
+ If there are any other neighbours configured, they will be removed.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv6 address of neighbour to be set.
+ :param link_layer_address: Link layer address.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type link_layer_address: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
+ neighbor = {"neighbor": [{"ip": ip_addr,
+ "link-layer-address": link_layer_address}, ]}
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, neighbor)
+
+ @staticmethod
+ def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
+ """Add the IPv6 neighbour.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param ip_addr: IPv6 address of neighbour to be set.
+ :param link_layer_address: Link layer address.
+ :type node: dict
+ :type interface: str
+ :type ip_addr: str
+ :type link_layer_address: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
+ "neighbor")
+ neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, neighbor)
+
+ @staticmethod
+ def remove_all_ipv6_neighbors(node, interface):
+ """Remove all IPv6 neighbours.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :type node: dict
+ :type interface: str
+ :return: Content of response.
+ :rtype: bytearray
+ """
+
+ path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
+ "neighbor")
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, None)
+
+ @staticmethod
+ def configure_interface_ethernet(node, interface, param, value):
+ """Configure the ethernet parameters of interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.ETH_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+ path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
+ param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def configure_interface_routing(node, interface, param, value):
+ """Configure the routing parameters of interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.ROUTING_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ path = ("interfaces", ("interface", "name", interface), "v3po:routing",
+ param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def configure_interface_vxlan(node, interface, param, value):
+ """Configure the VxLAN parameters of interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.VXLAN_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+
+ path = ("interfaces", ("interface", "name", interface), "v3po:vxlan",
+ param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
+
+ @staticmethod
+ def configure_interface_l2(node, interface, param, value):
+ """Configure the L2 parameters of interface.
+
+ :param node: Honeycomb node.
+ :param interface: The name of interface.
+ :param param: Parameter to configure (set, change, remove)
+ :param value: The value of parameter. If None, the parameter will be
+ removed.
+ :type node: dict
+ :type interface: str
+ :type param: str
+ :type value: str
+ :return: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the parameter is not valid.
+ """
+
+ if param not in InterfaceKeywords.L2_PARAMS:
+ raise HoneycombError("The parameter {0} is invalid.".format(param))
+ path = ("interfaces", ("interface", "name", interface), "v3po:l2",
+ param)
+ return InterfaceKeywords._set_interface_properties(
+ node, interface, path, value)
diff --git a/resources/libraries/python/HoneycombAPIKeywords.py b/resources/libraries/python/HoneycombAPIKeywords.py
deleted file mode 100644
index 0369a32d5b..0000000000
--- a/resources/libraries/python/HoneycombAPIKeywords.py
+++ /dev/null
@@ -1,543 +0,0 @@
-# Copyright (c) 2016 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:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Keywords used with Honeycomb.
-
-There are implemented keywords which work with:
-- Honeycomb operations
-- VPP Interfaces
-- Bridge domains
-
-The keywords make possible to put and get configuration data and to get
-operational data.
-"""
-
-from json import dumps
-
-from robot.api import logger
-
-from resources.libraries.python.HTTPRequest import HTTPCodes
-from resources.libraries.python.HoneycombSetup import HoneycombError
-from resources.libraries.python.HoneycombUtil import HoneycombUtil as HcUtil
-from resources.libraries.python.HoneycombUtil import DataRepresentation
-
-
-class OperationsKeywords(object):
- """Keywords which perform "operations" in Honeycomb.
-
- The keywords in this class are not a part of a specific area in Honeycomb,
- e.g.: interfaces or bridge domains, but they perform "operations" in any
- area of Honeycomb.
- """
-
- def __init__(self):
- pass
-
- @staticmethod
- def poll_oper_data(node):
- """Poll operational data.
-
- You can use this keyword when you configure something in Honeycomb and
- you want configuration data to make effect immediately, e.g.:
-
- | | Create Bridge Domain | ....
- | | Add Bridge Domain To Interface | ....
- | | Poll Oper Data | ....
- | | ${br}= | Get Oper Info About Bridge Domain | ....
-
- ..note:: This is not very reliable way how to poll operational data.
- This keyword is only temporary workaround and will be removed when this
- problem is solved in Honeycomb.
- :param node: Honeycomb node.
- :type: dict
- :raises HoneycombError: If it is not possible to poll operational data.
- """
-
- status_code, _ = HcUtil.\
- post_honeycomb_data(node, "poll_oper_data", data='',
- data_representation=DataRepresentation.NO_DATA,
- timeout=30)
- if status_code != HTTPCodes.OK:
- raise HoneycombError("It was not possible to poll operational data "
- "on node {0}.".format(node['host']))
-
-
-class InterfaceKeywords(object):
- """Keywords for Interface manipulation.
-
- Implements keywords which get configuration and operational data about
- vpp interfaces and set the interface's parameters using Honeycomb REST API.
- """
-
- def __init__(self):
- pass
-
- @staticmethod
- def _configure_interface(node, interface, data,
- data_representation=DataRepresentation.JSON):
- """Send interface configuration data and check the response.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :param data: Configuration data to be sent in PUT request.
- :param data_representation: How the data is represented.
- :type node: dict
- :type interface: str
- :type data: str
- :type data_representation: DataRepresentation
- :return: Content of response.
- :rtype: bytearray
- :raises HoneycombError: If the status code in response on PUT is not
- 200 = OK.
- """
-
- status_code, resp = HcUtil.\
- put_honeycomb_data(node, "config_vpp_interfaces", data,
- data_representation=data_representation)
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "The configuration of interface '{0}' was not successful. "
- "Status code: {1}.".format(interface, status_code))
- return resp
-
- @staticmethod
- def get_all_interfaces_cfg_data(node):
- """Get configuration data about all interfaces from Honeycomb.
-
- :param node: Honeycomb node.
- :type node: dict
- :return: Configuration data about all interfaces from Honeycomb.
- :rtype: list
- :raises HoneycombError: If it is not possible to get configuration data.
- """
-
- status_code, resp = HcUtil.get_honeycomb_data(node,
- "config_vpp_interfaces")
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Not possible to get configuration information about the "
- "interfaces. Status code: {0}.".format(status_code))
- try:
- intf = HcUtil.parse_json_response(resp, ("interfaces", "interface"))
- return intf
- except KeyError:
- return []
-
- @staticmethod
- def get_interface_cfg_info(node, interface):
- """Get configuration data about the given interface from Honeycomb.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :type node: dict
- :type interface: str
- :return: Configuration data about the given interface from Honeycomb.
- :rtype: dict
- """
-
- intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
- for intf in intfs:
- if intf["name"] == interface:
- return intf
- return {}
-
- @staticmethod
- def get_all_interfaces_oper_info(node):
- """Get operational data about all interfaces from Honeycomb.
-
- :param node: Honeycomb node.
- :type node: dict
- :return: Operational data about all interfaces from Honeycomb.
- :rtype: list
- :raises HoneycombError: If it is not possible to get operational data.
- """
-
- status_code, resp = HcUtil.get_honeycomb_data(node,
- "oper_vpp_interfaces")
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Not possible to get operational information about the "
- "interfaces. Status code: {0}.".format(status_code))
- try:
- intf = HcUtil.parse_json_response(resp, ("interfaces-state",
- "interface"))
- return intf
- except KeyError:
- return []
-
- @staticmethod
- def get_interface_oper_info(node, interface):
- """Get operational data about the given interface from Honeycomb.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :type node: dict
- :type interface: str
- :return: Operational data about the given interface from Honeycomb.
- :rtype: dict
- """
-
- intfs = InterfaceKeywords.get_all_interfaces_oper_info(node)
- for intf in intfs:
- if intf["name"] == interface:
- return intf
- return {}
-
- @staticmethod
- def set_interface_state(node, interface, state="up"):
- """Set VPP interface state.
-
- The keyword changes the administration state of interface to up or down
- depending on the parameter "state".
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :param state: The requested state, only "up" and "down" are valid
- values.
- :type node: dict
- :type interface: str
- :type state: str
- :return: Content of response.
- :rtype: bytearray
- :raises KeyError: If the argument "state" is nor "up" or "down".
- :raises HoneycombError: If the interface is not present on the node.
- """
-
- intf_state = {"up": "true",
- "down": "false"}
- intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
- for intf in intfs:
- if intf["name"] == interface:
- intf["enabled"] = intf_state[state.lower()]
- new_intf = {"interfaces": {"interface": intfs}}
- return InterfaceKeywords._configure_interface(node, interface,
- dumps(new_intf))
- raise HoneycombError("The interface '{0}' is not present on node "
- "'{1}'.".format(interface, node['host']))
-
- @staticmethod
- def set_interface_up(node, interface):
- """Set the administration state of VPP interface to up.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :type node: dict
- :type interface: str
- :return: Content of response
- :rtype: bytearray
- """
-
- return InterfaceKeywords.set_interface_state(node, interface, "up")
-
- @staticmethod
- def set_interface_down(node, interface):
- """Set the administration state of VPP interface to down.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :type node: dict
- :type interface: str
- :return: Content of response.
- :rtype: bytearray
- """
-
- return InterfaceKeywords.set_interface_state(node, interface, "down")
-
- @staticmethod
- def add_bridge_domain_to_interface(node, interface, bd_name,
- split_horizon_group=None, bvi=None):
- """Add a new bridge domain to an interface and set its parameters.
-
- :param node: Honeycomb node.
- :param interface: The name of interface.
- :param bd_name: Bridge domain name.
- :param split_horizon_group: Split-horizon group name.
- :param bvi: The bridged virtual interface.
- :type node: dict
- :type interface: str
- :type bd_name: str
- :type split_horizon_group: str
- :type bvi: str
- :return: Content of response.
- :rtype: bytearray
- :raises HoneycombError: If the interface is not present on the node.
- """
-
- intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
- v3po_l2 = {"bridge-domain": str(bd_name)}
- if split_horizon_group:
- v3po_l2["split-horizon-group"] = str(split_horizon_group)
- if bvi:
- v3po_l2["bridged-virtual-interface"] = str(bvi)
- for intf in intfs:
- if intf["name"] == interface:
- intf["v3po:l2"] = v3po_l2
- new_intf = {"interfaces": {"interface": intfs}}
- return InterfaceKeywords._configure_interface(node, interface,
- dumps(new_intf))
- raise HoneycombError("The interface '{0}' is not present on node "
- "'{1}'.".format(interface, node['host']))
-
-
-class BridgeDomainKeywords(object):
- """Keywords for Bridge domain manipulation.
-
- Implements keywords which get configuration and operational data about
- bridge domains and put the bridge domains' parameters using Honeycomb REST
- API.
- """
-
- def __init__(self):
- pass
-
- @staticmethod
- def _create_json_bridge_domain_info(name, **kwargs):
- """Generate bridge domain information in the structure as it is expected
- by Honeycomb.
-
- The generated data structure is as follows:
- {
- "bridge-domains": {
- "bridge-domain": [
- {
- "name": "bd_name",
- "flood": "false",
- "forward": "false",
- "learn": "false",
- "unknown-unicast-flood": "false",
- "arp-termination": "false"
- }
- ]
- }
- }
-
- :param name: The name of new bridge-domain.
- :param kwargs: named arguments:
- flood (bool): If True, flooding is enabled.
- forward (bool): If True, packet forwarding is enabled.
- learn (bool): If True, learning is enabled.
- uu_flood (bool): If True, unknown unicast flooding is enabled.
- arp_termination (bool): If True, ARP termination is enabled.
- :type name: str
- :type kwargs: dict
- :return: Bridge domain information in format suitable for Honeycomb.
- :rtype: dict
- :raises KeyError: If at least one of kwargs items is missing.
- """
-
- brd_info = {
- "bridge-domains": {
- "bridge-domain": [
- {"name": name,
- "flood": str(kwargs["flood"]).lower(),
- "forward": str(kwargs["forward"]).lower(),
- "learn": str(kwargs["learn"]).lower(),
- "unknown-unicast-flood": str(kwargs["uu_flood"]).lower(),
- "arp-termination": str(kwargs["arp_termination"]).lower()},
- ]
- }
- }
-
- return brd_info
-
- @staticmethod
- def create_bridge_domain(node, name, flood=True, forward=True, learn=True,
- uu_flood=True, arp_termination=False):
- """Create a bridge domain using Honeycomb.
-
- This keyword adds a new bridge domain to the list of bridge domains and
- sets its parameters. The existing bridge domains are untouched.
- :param node: Node with Honeycomb where the bridge domain should be
- created.
- :param name: The name of new bridge-domain.
- :param flood: If True, flooding is enabled.
- :param forward: If True, packet forwarding is enabled.
- :param learn: If True, learning is enabled.
- :param uu_flood: If True, unknown unicast flooding is enabled.
- :param arp_termination: If True, ARP termination is enabled.
- :type node: dict
- :type name: str
- :type flood: bool
- :type forward: bool
- :type learn: bool
- :type uu_flood: bool
- :type arp_termination: bool
- :raises HoneycombError: If the bridge domain already exists or it has
- not been created.
- """
-
- existing_brds = BridgeDomainKeywords.\
- get_all_bds_cfg_data(node, ignore_404=True)
-
- for brd in existing_brds:
- if brd["name"] == name:
- raise HoneycombError("Bridge domain {0} already exists.".
- format(name))
-
- brd_info = BridgeDomainKeywords._create_json_bridge_domain_info(
- name, flood=flood, forward=forward, learn=learn, uu_flood=uu_flood,
- arp_termination=arp_termination)
- for brd in existing_brds:
- brd_info["bridge-domains"]["bridge-domain"].append(brd)
-
- status_code, _ = HcUtil.put_honeycomb_data(node, "config_bridge_domain",
- dumps(brd_info))
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Bridge domain {0} was not created. "
- "Status code: {01}.".format(name, status_code))
-
- @staticmethod
- def get_all_bds_oper_data(node):
- """Get operational data about all bridge domains from Honeycomb.
-
- :param node: Honeycomb node.
- :type node: dict
- :return: Operational data about all bridge domains from Honeycomb.
- :rtype: list
- :raises HoneycombError: If it is not possible to get information about
- the bridge domains.
- """
-
- status_code, resp = HcUtil.get_honeycomb_data(node,
- "oper_bridge_domains")
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Not possible to get information about the bridge domains. "
- "Status code: {0}.".format(status_code))
- try:
- br_domains = HcUtil.parse_json_response(resp, ("bridge-domains",
- "bridge-domain"))
- except KeyError:
- return []
- return br_domains
-
- @staticmethod
- def get_bd_oper_data(node, name):
- """Get operational data about the given bridge domain from Honeycomb.
-
- :param node: Honeycomb node.
- :param name: The name of bridge domain.
- :type node: dict
- :type name: str
- :return: Operational data about the given bridge domain from Honeycomb.
- :rtype: dict
- """
-
- br_domains = BridgeDomainKeywords.get_all_bds_oper_data(node)
- for br_domain in br_domains:
- if br_domain["name"] == name:
- br_domain["name"] = br_domain["name"]
- return br_domain
- return {}
-
- @staticmethod
- def get_all_bds_cfg_data(node, ignore_404=False):
- """Get configuration data about all bridge domains from Honeycomb.
-
- :param node: Honeycomb node.
- :param ignore_404: If True, the error 404 is ignored.
- :type node: dict
- :type ignore_404: bool
- :return: Configuration data about all bridge domains from Honeycomb.
- :rtype: list
- :raises HoneycombError: If it is not possible to get information about
- the bridge domains.
- """
-
- status_code, resp = HcUtil.get_honeycomb_data(node,
- "config_bridge_domain")
- if status_code != HTTPCodes.OK:
- if ignore_404 and status_code == HTTPCodes.NOT_FOUND:
- br_domains = list()
- logger.debug("Error 404 ignored")
- else:
- raise HoneycombError(
- "Not possible to get information about the bridge domains. "
- "Status code: {0}.".format(status_code))
- else:
- try:
- br_domains = HcUtil.parse_json_response(resp, ("bridge-domains",
- "bridge-domain"))
- except KeyError:
- return []
- return br_domains
-
- @staticmethod
- def get_bd_cfg_data(node, name):
- """Get configuration data about the given bridge domain from Honeycomb.
-
- :param node: Honeycomb node.
- :param name: The name of bridge domain.
- :type node: dict
- :type name: str
- :return: Configuration data about the given bridge domain from
- Honeycomb.
- :rtype: dict
- """
-
- br_domains = BridgeDomainKeywords.get_all_bds_cfg_data(node)
- for br_domain in br_domains:
- if br_domain["name"] == name:
- return br_domain
- return {}
-
- @staticmethod
- def delete_all_bridge_domains(node):
- """Delete all bridge domains on Honeycomb node.
-
- :param node: Honeycomb node.
- :type node: dict
- :return: Response from DELETE request.
- :rtype: str
- :raises HoneycombError: If it is not possible to delete all bridge
- domains.
- """
-
- status_code, resp = HcUtil.delete_honeycomb_data(node,
- "config_bridge_domain")
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Not possible to delete all bridge domains. "
- "Status code: {0}.".format(status_code))
- return resp
-
- @staticmethod
- def remove_bridge_domain(node, name):
- """Remove one bridge domain from Honeycomb.
-
- :param node: Honeycomb node.
- :param name: Name of the bridge domain to be removed.
- :type node: dict
- :type name: str
- :return: True if the bridge domain was removed.
- :rtype: bool
- :raises HoneycombError: If it is not possible to remove the bridge
- domain.
- """
-
- br_domains = BridgeDomainKeywords.get_all_bds_cfg_data(node)
- for br_domain in br_domains:
- if br_domain["name"] == name:
- br_domains.remove(br_domain)
- brd_info = {"bridge-domains": {"bridge-domain": br_domains}}
- status_code, _ = HcUtil.put_honeycomb_data(
- node, "config_bridge_domain", dumps(brd_info))
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Bridge domain '{0}' was not deleted. "
- "Status code: {1}.".format(name, status_code))
- return True
-
- raise HoneycombError("Not possible to delete bridge domain '{0}'. The "
- "bridge domain was not found".format(name))
diff --git a/resources/libraries/python/HoneycombSetup.py b/resources/libraries/python/HoneycombSetup.py
index bd2f3087c4..979b501522 100644
--- a/resources/libraries/python/HoneycombSetup.py
+++ b/resources/libraries/python/HoneycombSetup.py
@@ -13,8 +13,6 @@
"""Implementation of keywords for Honeycomb setup."""
-from xml.etree import ElementTree as ET
-
from robot.api import logger
from resources.libraries.python.topology import NodeType
@@ -186,93 +184,3 @@ class HoneycombSetup(object):
logger.info("Honeycomb on node {0} has stopped".
format(node['host']))
return True
-
- @staticmethod
- def add_vpp_to_honeycomb_network_topology(nodes):
- """Add vpp node to Honeycomb network topology.
-
- :param nodes: All nodes in test topology.
- :type nodes: dict
- :return: Status code and response content from PUT requests.
- :rtype: tuple
- :raises HoneycombError: If a node was not added to Honeycomb topology.
-
- Reads HTML path from template file config_topology_node.url.
- Path to the node to be added, e.g.:
- ("/restconf/config/network-topology:network-topology"
- "/topology/topology-netconf/node/")
- There must be "/" at the end, as generated node name is added at the
- end.
-
- Reads payload data from template file add_vpp_to_topology.xml.
- Information about node as XML structure, e.g.:
- <node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
- <node-id>
- {vpp_host}
- </node-id>
- <host xmlns="urn:opendaylight:netconf-node-topology">
- {vpp_ip}
- </host>
- <port xmlns="urn:opendaylight:netconf-node-topology">
- {vpp_port}
- </port>
- <username xmlns="urn:opendaylight:netconf-node-topology">
- {user}
- </username>
- <password xmlns="urn:opendaylight:netconf-node-topology">
- {passwd}
- </password>
- <tcp-only xmlns="urn:opendaylight:netconf-node-topology">
- false
- </tcp-only>
- <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">
- 0
- </keepalive-delay>
- </node>
- NOTE: The placeholders:
- {vpp_host}
- {vpp_ip}
- {vpp_port}
- {user}
- {passwd}
- MUST be there as they are replaced by correct values.
- """
- path = HcUtil.read_path_from_url_file("config_topology_node")
- try:
- xml_data = ET.parse("{0}/add_vpp_to_topology.xml".
- format(Const.RESOURCES_TPL_HC))
- except ET.ParseError as err:
- raise HoneycombError(repr(err))
- data = ET.tostring(xml_data.getroot())
-
- headers = {"Content-Type": "application/xml"}
-
- status_codes = []
- responses = []
- for node_name, node in nodes.items():
- if node['type'] == NodeType.DUT:
- try:
- payload = data.format(
- vpp_host=node_name,
- vpp_ip=node["host"],
- vpp_port=node['honeycomb']["netconf_port"],
- user=node['honeycomb']["user"],
- passwd=node['honeycomb']["passwd"])
- status_code, resp = HTTPRequest.put(
- node=node,
- path="{0}/{1}".format(path, node_name),
- headers=headers,
- payload=payload)
- if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "VPP {0} was not added to topology. "
- "Status code: {1}.".format(node["host"],
- status_code))
-
- status_codes.append(status_code)
- responses.append(resp)
-
- except HTTPRequestError as err:
- raise HoneycombError("VPP {0} was not added to topology.".
- format(node["host"]), repr(err))
- return status_codes, responses
diff --git a/resources/libraries/python/HoneycombUtil.py b/resources/libraries/python/HoneycombUtil.py
index 7ffa6430ff..644cf62c43 100644
--- a/resources/libraries/python/HoneycombUtil.py
+++ b/resources/libraries/python/HoneycombUtil.py
@@ -22,7 +22,7 @@ be used directly in tests. Use keywords implemented in the module
HoneycombAPIKeywords instead.
"""
-from json import loads
+from json import loads, dumps
from enum import Enum, unique
from robot.api import logger
@@ -42,7 +42,7 @@ class DataRepresentation(Enum):
# Headers used in requests. Key - content representation, value - header.
HEADERS = {DataRepresentation.NO_DATA:
- {}, # Must be empty.
+ {}, # It must be empty dictionary.
DataRepresentation.JSON:
{"Content-Type": "application/json",
"Accept": "text/plain"},
@@ -136,51 +136,153 @@ class HoneycombUtil(object):
return path
@staticmethod
- def parse_json_response(response, path=None):
- """Parse data from response string in JSON format according to given
- path.
-
- :param response: JSON formatted string.
- :param path: Path to navigate down the data structure.
- :type response: str
+ def find_item(data, path):
+ """Find a data item (single leaf or sub-tree) in data received from
+ Honeycomb REST API.
+
+ Path format:
+ The path is a tuple with items navigating to requested data. The items
+ can be strings or tuples:
+ - string item represents a dictionary key in data,
+ - tuple item represents list item in data.
+
+ Example:
+ data = \
+ {
+ "interfaces": {
+ "interface": [
+ {
+ "name": "GigabitEthernet0/8/0",
+ "enabled": "true",
+ "type": "iana-if-type:ethernetCsmacd",
+ },
+ {
+ "name": "local0",
+ "enabled": "false",
+ "type": "iana-if-type:ethernetCsmacd",
+ }
+ ]
+ }
+ }
+
+ path = ("interfaces", ("interface", "name", "local0"), "enabled")
+ This path points to "false".
+
+ The tuple ("interface", "name", "local0") consists of:
+ index 0 - dictionary key pointing to a list,
+ index 1 - key which identifies an item in the list, it is also marked as
+ the key in corresponding yang file.
+ index 2 - key value.
+
+ :param data: Data received from Honeycomb REST API.
+ :param path: Path to data we want to find.
+ :type data: dict
:type path: tuple
- :return: JSON dictionary/list tree.
- :rtype: list
+ :return: Data represented by path.
+ :rtype: str, dict, or list
+ :raises HoneycombError: If the data has not been found.
"""
- data = loads(response)
- if path:
- data = HoneycombUtil._parse_json_tree(data, path)
- if not isinstance(data, list):
- data = [data, ]
+ for path_item in path:
+ try:
+ if isinstance(path_item, str):
+ data = data[path_item]
+ elif isinstance(path_item, tuple):
+ for data_item in data[path_item[0]]:
+ if data_item[path_item[1]] == path_item[2]:
+ data = data_item
+ except KeyError as err:
+ raise HoneycombError("Data not found: {0}".format(err))
return data
@staticmethod
- def _parse_json_tree(data, path):
- """Retrieve data addressed by path from python representation of JSON
- object.
+ def remove_item(data, path):
+ """Remove a data item (single leaf or sub-tree) in data received from
+ Honeycomb REST API.
- :param data: Parsed JSON dictionary tree.
- :param path: Path to navigate down the dictionary tree.
+ :param data: Data received from Honeycomb REST API.
+ :param path: Path to data we want to remove.
:type data: dict
:type path: tuple
- :return: Data from specified path.
- :rtype: list, dict or str
+ :return: Original data without removed part.
+ :rtype: dict
"""
- count = 0
- for key in path:
- if isinstance(data, dict):
- data = data[key]
- count += 1
- elif isinstance(data, list):
- result = []
- for item in data:
- result.append(HoneycombUtil._parse_json_tree(item,
- path[count:]))
- return result
- return data
+ origin_data = previous_data = data
+ try:
+ for path_item in path:
+ previous_data = data
+ if isinstance(path_item, str):
+ data = data[path_item]
+ elif isinstance(path_item, tuple):
+ for data_item in data[path_item[0]]:
+ if data_item[path_item[1]] == path_item[2]:
+ data = data_item
+ except KeyError as err:
+ logger.debug("Data not found: {0}".format(err))
+ return origin_data
+
+ if isinstance(path[-1], str):
+ previous_data.pop(path[-1])
+ elif isinstance(path[-1], tuple):
+ previous_data[path[-1][0]].remove(data)
+ if not previous_data[path[-1][0]]:
+ previous_data.pop(path[-1][0])
+
+ return origin_data
+
+ @staticmethod
+ def set_item_value(data, path, new_value):
+ """Set or change the value (single leaf or sub-tree) in data received
+ from Honeycomb REST API.
+
+ If the item is not present in the data structure, it is created.
+
+ :param data: Data received from Honeycomb REST API.
+ :param path: Path to data we want to change or create.
+ :param new_value: The value to be set.
+ :type data: dict
+ :type path: tuple
+ :type new_value: str, dict or list
+ :return: Original data with the new value.
+ :rtype: dict
+ """
+
+ origin_data = data
+ for path_item in path[:-1]:
+ if isinstance(path_item, str):
+ try:
+ data = data[path_item]
+ except KeyError:
+ data[path_item] = {}
+ data = data[path_item]
+ elif isinstance(path_item, tuple):
+ try:
+ flag = False
+ index = 0
+ for data_item in data[path_item[0]]:
+ if data_item[path_item[1]] == path_item[2]:
+ data = data[path_item[0]][index]
+ flag = True
+ break
+ index += 1
+ if not flag:
+ data[path_item[0]].append({path_item[1]: path_item[2]})
+ data = data[path_item[0]][-1]
+ except KeyError:
+ data[path_item] = []
+
+ if not path[-1] in data.keys():
+ data[path[-1]] = {}
+
+ if isinstance(new_value, list) and isinstance(data[path[-1]], list):
+ for value in new_value:
+ data[path[-1]].append(value)
+ else:
+ data[path[-1]] = new_value
+
+ return origin_data
@staticmethod
def get_honeycomb_data(node, url_file):
@@ -196,7 +298,8 @@ class HoneycombUtil(object):
"""
path = HoneycombUtil.read_path_from_url_file(url_file)
- return HTTPRequest.get(node, path)
+ status_code, resp = HTTPRequest.get(node, path)
+ return status_code, loads(resp)
@staticmethod
def put_honeycomb_data(node, url_file, data,
@@ -211,7 +314,7 @@ class HoneycombUtil(object):
:param data_representation: How the data is represented.
:type node: dict
:type url_file: str
- :type data: str
+ :type data: dict, str
:type data_representation: DataRepresentation
:return: Status code and content of response.
:rtype: tuple
@@ -224,6 +327,8 @@ class HoneycombUtil(object):
except AttributeError as err:
raise HoneycombError("Wrong data representation: {0}.".
format(data_representation), repr(err))
+ if data_representation == DataRepresentation.JSON:
+ data = dumps(data)
path = HoneycombUtil.read_path_from_url_file(url_file)
return HTTPRequest.put(node=node, path=path, headers=header,
@@ -244,7 +349,7 @@ class HoneycombUtil(object):
giving up.
:type node: dict
:type url_file: str
- :type data: str
+ :type data: dict, str
:type data_representation: DataRepresentation
:type timeout: int
:return: Status code and content of response.
@@ -258,6 +363,8 @@ class HoneycombUtil(object):
except AttributeError as err:
raise HoneycombError("Wrong data representation: {0}.".
format(data_representation), repr(err))
+ if data_representation == DataRepresentation.JSON:
+ data = dumps(data)
path = HoneycombUtil.read_path_from_url_file(url_file)
return HTTPRequest.post(node=node, path=path, headers=header,