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

Testing remote capabilities using virtual networks #149

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Testing remote capabilities using virtual networks #149

wants to merge 8 commits into from

Conversation

guilledk
Copy link
Collaborator

This starts to address #124

pytest-vnet does most of the heavy work, creates a docker container from this docker image based on debian, it installs the latest mininet release from its github and sets up python build essentials, on the first run it will install python inside the container and save a snapshot for each python version it installs, to avoid repeating the process.

From mininet.org: "Mininet creates a realistic virtual network, running real kernel, switch and application code, on a single machine (VM, cloud or native)"

To use this virutal net, pytest-vnet allows us to mark our regular test functions with the decorator @run_in_netvm, here is a full example:

@run_in_netvm
def test_vsocket_hello():

    s3 = vnet.addSwitch("s3")

    @as_host(vnet, 'h1', '10.0.0.1', s3)
    def receiver():
        import socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.bind(('', 50007))
            s.listen(1)
            conn, addr = s.accept()
            with conn:
                data = conn.recv(1024)
                assert data == b"Hello world through a virtual socket!"

    @as_host(vnet, 'h2', '10.0.0.2', s3)
    def sender():
        import socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.connect(('10.0.0.1', 50007))
            s.sendall("Hello world through a virtual socket!".encode('utf-8'))

    vnet.start()
    receiver.start_host()
    sender.start_host()
    receiver.proc.wait(timeout=3)

Test functions marked with @run_in_netvm will be loaded as a script inside the running docker container, and the following code will be injected on them:

import sys
import logging
import traceback
"""
a bunch of sys.path.appends to hook the vms python env to the host
"""
from mininet.net import Mininet
from mininet.node import Controller
# To disable resource limit error message in mininet
from mininet.log import setLogLevel
setLogLevel("critical")
# Additional tools inside vm scripts
from pytest_vnet import as_script, as_host
vnet = Mininet(controller=Controller)
try:
    vnet.addController('c0')
    """
    actuall func code
    """
except Exception as e:
    sys.stderr.write(traceback.format_exc())

vnet.stop()

As you can see by default a bunch of packages are imported and an empty virtual net is created: vnet, this network gets automatically stopped at the end of the script. That try catch is to properly relay exceptions to pytest in the future, for now, the traceback format exec gets thrown into stderr

Then each function marked with @as_host gets loaded to the netvm as a separate script but also it will create a new mininet host and link to the network, here is the decorator code:

def as_host(vnet, hostname, addr, link):

    def wrapper(func):
        func = as_script(func)  # only inject sys path appends and nothing else
        func.host = vnet.addHost(hostname, ip=addr)
        vnet.addLink(func.host, link)
        def _start_proc():
            func.proc = func.host.popen(["python3", func.path])
        func.start_host = _start_proc
        return func

    return wrapper

To actually start the process one must call as_host_wrapped_func.start_host().

disclaimer: pytest-vnet is in very early development

@guilledk guilledk added enhancement New feature or request experiment Exploratory design and testing labels Aug 30, 2020
@guilledk guilledk self-assigned this Aug 30, 2020
@guilledk
Copy link
Collaborator Author

Oh we need to figure out how to run docker inside the travis vms

@goodboy
Copy link
Owner

goodboy commented Aug 30, 2020

Oh we need to figure out how to run docker inside the travis vms

Yah, I've done it before in that other project I pointed to prior.
Yaml line should be here.

@guilledk guilledk closed this Aug 30, 2020
@guilledk guilledk reopened this Aug 30, 2020
@goodboy goodboy self-requested a review August 31, 2020 00:16
@guilledk
Copy link
Collaborator Author

Also mininet has resiliency testing stuff built in, for example in mininet/examples/simpleperf.py:

class SingleSwitchTopo( Topo ):
    "Single switch connected to n hosts."
    def build( self, n=2, lossy=True ):
        switch = self.addSwitch('s1')
        for h in range(n):
            # Each host gets 50%/n of system CPU
            host = self.addHost('h%s' % (h + 1),
                                cpu=.5 / n)
            if lossy:
                # 10 Mbps, 5ms delay, 10% packet loss
                self.addLink(host, switch,
                             bw=10, delay='5ms', loss=10, use_htb=True)
            else:
                # 10 Mbps, 5ms delay, no packet loss
                self.addLink(host, switch,
                             bw=10, delay='5ms', loss=0, use_htb=True)

All the examples here are very useful.

@guilledk guilledk marked this pull request as ready for review August 31, 2020 13:51
@@ -4,46 +4,6 @@ sudo: required

matrix:
include:
- name: "Windows, Python Latest: multiprocessing"
Copy link
Owner

Choose a reason for hiding this comment

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

I guess we should look into if anyone has had this problem before we drop all this.

@guilledk guilledk closed this Sep 1, 2020
@guilledk guilledk reopened this Sep 1, 2020
@goodboy
Copy link
Owner

goodboy commented Oct 20, 2020

@guilledk We dropped travisCI once the debugger stuff landed.
Maybe rebase this and see if we can at least get a clean run?

@guilledk
Copy link
Collaborator Author

guilledk commented Apr 28, 2021

@goodboy So whats the plan here, wanna give this another shot? I recently learned how to run docker containers inside github's CI

@goodboy
Copy link
Owner

goodboy commented May 5, 2021

@guilledk I think if we're gonna do it let's use a real use case:

  • spawn a streaming daemon try to connect and stream from it over a wireguard tunnel
  • spawn rpc daemon and see if you can route requests over tor and back

@goodboy
Copy link
Owner

goodboy commented May 23, 2023

Another tool that might be handy if/when we get back to this:
https://manpages.ubuntu.com/manpages/trusty/man1/wirefilter.1.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request experiment Exploratory design and testing testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants