Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ShellCommandHelper and add OvsHelper #934

Merged
merged 9 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions device_coupler/ovs_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Module to help setup OVS bridges, VxLANs and other virt network components"""

from __future__ import absolute_import, division

from functools import partial
from python_lib.shell_command_helper import ShellCommandHelper
from utils import get_logger


class OvsHelper:
"""Class to build OVS bridges, VxLANs and other network components"""
DEFAULT_VXLAN_PORT = 4789
VXLAN_CMD_FMT = 'ip link add %s type vxlan id %s remote %s dstport %s srcport %s %s nolearning'

def __init__(self):
self._logger = get_logger('OvsHelper')
self._run_shell = partial(ShellCommandHelper().run_cmd, capture=True)
self._run_shell_no_raise = partial(ShellCommandHelper().run_cmd, capture=True, strict=False)

def create_vxlan_endpoint(self, port, remote_ip, vni, local_ip=None):
"""Creates a VxLAN endpoint"""
interface = "vxlan%s" % port
self.remove_vxlan_endpoint(interface)
self._logger.info("Creating VxLAN endpoint %s", interface)
vxlan_cmd = 'sudo ' + self.VXLAN_CMD_FMT % (
interface, vni, remote_ip, self.DEFAULT_VXLAN_PORT,
self.DEFAULT_VXLAN_PORT, self.DEFAULT_VXLAN_PORT)
self._run_shell(vxlan_cmd)
self._run_shell('sudo ip link set %s up' % interface)
if local_ip:
self._run_shell('sudo ip addr add %s dev %s' % (local_ip, interface))
return interface

def remove_vxlan_endpoint(self, interface):
"""Clears VxLAN endpoint"""
self._logger.info('Removing vxlan interface %s', interface)
self._run_shell_no_raise('sudo ip link set %s down' % interface)
self._run_shell_no_raise('sudo ip link del %s' % interface)
self._run_shell_no_raise('sudo ovs-vsctl del-port t1sw1 %s' % interface)

def create_ovs_bridge(self, name):
"""Creates OVS bridge"""
self._logger.info('Creating OVS bridge %s', name)
self._run_shell('sudo ovs-vsctl add-br %s' % name)

def delete_ovs_bridge(self, name):
"""Delete ovs bridge"""
self._logger.info('Deleting OVS bridge %s', name)
self._run_shell_no_raise('sudo ovs-vsctl del-br %s' % name)

def add_iface_to_bridge(self, bridge, iface):
"""Add interface to OVS bridge"""
self._logger.info('Adding interface %s to bridge %s', iface, bridge)
self._run_shell('sudo ovs-vsctl add-port %s %s' % (bridge, iface))

def set_native_vlan(self, interface, vlan):
"""Set native VLAN to port on OVS bridge"""
self._logger.info('Enabling native VLAN %s on interface %s', vlan, interface)
self._run_shell('sudo ovs-vsctl set port %s tag=%s' % (interface, vlan))

def set_trunk_vlan(self, interface, vlans):
"""Takes an array of VLANs and sets them as trunk VLANs for the port on OVS bridge"""
self._logger.info('Enabling trunk VLANs %s on interface %s', vlans, interface)
vlan_str = ",".join(str(vlan) for vlan in vlans)
self._run_shell('sudo ovs-vsctl set port %s trunks=%s' % (interface, vlan_str))

def create_faux_device(self, index):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we going to refactor cmd/faux to python?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a good idea long term, but I am not working on it atm. I just need the faux as a testing tool and simply running it as a shell script works for me.

"""Creates faux docker container daq-faux-<index>"""
self._run_shell('sudo cmd/faux %s' % index)
iface = 'faux-eth0'
prefix = int(index / 256) + 1
suffix = index % 256
ip_addr = '192.168.%s.%s' % (prefix, suffix)
gateway = '192.168.1.0'
container = 'daq-faux-%s' % index

self._run_shell('ip addr flush %s' % iface, docker_container=container)
self._run_shell('ip addr add %s/16 dev %s' % (ip_addr, iface), docker_container=container)
self._run_shell('ip route add default via %s' % gateway, docker_container=container)
26 changes: 26 additions & 0 deletions device_coupler/simulate_access_switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Script that creates an OVS access switch with devices."""

from __future__ import absolute_import
from ovs_helper import OvsHelper


ovs_helper = OvsHelper()


def add_devices_to_br(bridge, num_devices):
for index in range(1, num_devices + 1):
ovs_helper.create_faux_device(index)
iface = "faux-%s" % index
ovs_helper.add_iface_to_bridge(bridge, iface)
ovs_helper.set_native_vlan(iface, 200 + index * 10)


def main():
bridge = 'br0'
num_devices = 3
ovs_helper.create_ovs_bridge(bridge)
add_devices_to_br(bridge, num_devices)


if __name__ == "__main__":
main()
31 changes: 31 additions & 0 deletions device_coupler/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Utility Functions"""
from __future__ import absolute_import
import logging
import sys


def get_logger(logname):
"""Create and return a logger object."""
logger = logging.getLogger(logname)
logger.setLevel(logging.INFO)

stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.INFO)
stdout_handler.setFormatter(
logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(stdout_handler)

logfile_handler = logging.FileHandler('/tmp/device_coupler_log')
logfile_handler.setLevel(logging.INFO)
logfile_handler.setFormatter(
logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(logfile_handler)

return logger


def enable_debug_logs(logger):
"""Enable debug logs for logger"""
logger.setLevel(logging.DEBUG)
for handler in logger.handlers:
handler.setLevel(logging.DEBUG)
3 changes: 3 additions & 0 deletions python_lib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Lib module for daq sub units"""

pass
File renamed without changes.
2 changes: 1 addition & 1 deletion shunt/vxlan_over_ssh.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Module to build VxLAN tunnels over SSH tunnels using shell commands"""

from __future__ import absolute_import
from shunt.shell_command_helper import ShellCommandHelper
from python_lib.shell_command_helper import ShellCommandHelper


def build_ssh_tunnel(ssh_in_port, ssh_out_port, remote_host, reverse=False):
Expand Down
2 changes: 2 additions & 0 deletions testing/shunt/Dockerfile.shunthost
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ COPY ./testing/shunt/id_rsa.pub .ssh/
COPY ./testing/shunt/authorized_keys .ssh/
COPY ./testing/shunt/start_shunt_host ./

RUN mkdir -p python_lib
RUN mkdir -p shunt
RUN mkdir -p testing
RUN mkdir -p testing/shunt

COPY ./python_lib python_lib
COPY ./shunt shunt
COPY ./testing/shunt testing/shunt

Expand Down
2 changes: 1 addition & 1 deletion testing/shunt/start_shunt_host
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
host=$1
service ssh start

export PYTHONPATH=$PYTHONPATH:/root/shunt
export PYTHONPATH=$PYTHONPATH:/root/shunt:/root/python_lib

python3 testing/shunt/build_vxlan_ssh_conn.py $host

Expand Down