diff options
Diffstat (limited to 'resources/libraries/python/honeycomb/IPv6Management.py')
-rw-r--r-- | resources/libraries/python/honeycomb/IPv6Management.py | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/resources/libraries/python/honeycomb/IPv6Management.py b/resources/libraries/python/honeycomb/IPv6Management.py new file mode 100644 index 0000000000..deec041103 --- /dev/null +++ b/resources/libraries/python/honeycomb/IPv6Management.py @@ -0,0 +1,147 @@ +# Copyright (c) 2017 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 for setup and testing of Honeycomb's control-plane interface +using IPv6. +""" + +from resources.libraries.python.ssh import SSH + + +class IPv6Management(object): + """Utilities for managing IPv6 contol-plane interfaces.""" + + def __init__(self): + pass + + @staticmethod + def get_interface_name_by_mac(node, mac): + """Get the name of an interface using its MAC address. + + :param node: Node in topology. + :param mac: MAC address. + :type node: dict + :type mac: str + :returns: Name of the interface. + :rtype: str + :raises RuntimeError: If no interface is found. + """ + + cmd = " | ".join([ + "fgrep -ls '{0}' /sys/class/net/*/address".format(mac), + "awk -F '/' '{print $5}'" + ]) + + ssh = SSH() + ssh.connect(node) + ret_code, stdout, _ = ssh.exec_command(cmd) + + if ret_code == 0: + return stdout.strip() + else: + raise RuntimeError("No interface found using the specified MAC " + "address.") + + @staticmethod + def clear_interface_configuration(node, interface): + """Remove all configured IP addresses from the specified interface + and set it into down state. + + :param node: Node in topology. + :param interface: Name of an interface on the node. + :type node: dict + :type interface: str + :raises RuntimeError: If the configuration could not be cleared. + """ + + cmd = " && ".join([ + "sudo ip addr flush dev {interface}".format(interface=interface), + "sudo ip link set dev {interface} down".format(interface=interface) + ]) + + ssh = SSH() + ssh.connect(node) + ret_code, _, _ = ssh.exec_command(cmd) + if ret_code != 0: + raise RuntimeError("Could not clear interface configuration.") + + @staticmethod + def set_management_interface_address(node, interface, address, prefix): + """Configure an IP address on the specified interface. + + :param node: Node in topology. + :param interface: Name of an interface on the node. + :param address: IP address to configure. + :param prefix: IP network prefix. + :type node: dict + :type interface: str + :type address: str + :type prefix: int + :raises RuntimeError: If the configuration fails. + """ + + ssh = SSH() + ssh.connect(node) + + # Enable IPv6 for only the specified interface + cmd = "sudo sysctl net.ipv6.conf.{0}.disable_ipv6=0".format(interface) + + ret_code, _, _ = ssh.exec_command(cmd) + if ret_code != 0: + raise RuntimeError("Could not enable IPv6 on interface.") + + # Configure IPv6 address on the interface + cmd = "sudo ip address add {address}/{prefix} dev {interface}".format( + interface=interface, + address=address, + prefix=prefix) + + ret_code, _, _ = ssh.exec_command(cmd) + if ret_code != 0: + raise RuntimeError("Could not configure IP address on interface.") + + # Set the interface up + cmd = "sudo ip link set {interface} up".format(interface=interface) + + ret_code, _, _ = ssh.exec_command(cmd) + if ret_code != 0: + raise RuntimeError("Could not change the interface to 'up' state.") + + @staticmethod + def configure_control_interface_tunnel(node, src_port, dst_ip, dst_port): + """Configure a tunnel on the specified node, tunelling any IPv4 traffic + from one port to the specified address. + + :param node: Node in topology. + :param src_port: Port to tunnel traffic from. + :param dst_ip: IP address to tunnel traffic to. + :param dst_port: Port to tunnel traffic to. + :type node: dict + :type src_port: int + :type dst_ip: str + :type dst_port: int + :raises RuntimeError: If tunnel creation is not successful. + """ + + cmd = "nohup socat TCP4-LISTEN:{src_port},fork,su=nobody " \ + "TCP6:[{dst_ip}]:{dst_port} $@ > " \ + "/tmp/socat.log 2>&1 &".format( + src_port=src_port, + dst_ip=dst_ip, + dst_port=dst_port) + + ssh = SSH() + ssh.connect(node) + ret_code, _, _ = ssh.exec_command_sudo(cmd) + if ret_code != 0: + raise RuntimeError("Could not configure tunnel.") |