-1

I am new to Mininet and I am trying to find a way to use a script in python to execute a few tests using Mininet. More precisely I want to build topology and send a few xmlrpc request from one host to another. I've recently found how to use mininet API. The problem is that I can't connect to the server from the client o get a response, I've tested using telnet 10.0.0.x 12345 command from the client host and got a connection denial. Here is the code:

topology_test.py

import subprocess
from time import time, sleep
from signal import SIGINT
from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client as cl
from mininet.util import pmonitor
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel, info
from mininet.cli import CLI


# mininet topology
class MyTopology(Topo):
    def build(self, n=2):
        switch = self.addSwitch("s1")
        embedder = self.addHost("embedder")
        self.addLink(embedder, switch)
        # Python's range(N) generates 0..N-1
        for h in range(n):
            host = self.addHost("server%s" % (h + 1))
            self.addLink(host, switch)


def simpleTest():
    "Create and test a simple network"
    output = subprocess.run(["sudo", "mn", "-c"])
    print(output)
    seconds = 10
    topo = MyTopology(n=4)
    net = Mininet(topo)
    net.start()
    print("Dumping host connections")
    dumpNodeConnections(net.hosts)
    print("Testing network connectivity")
    net.pingAll()

    h1 = net.get("server1")
    p1 = h1.popen("python3 myServer.py -i %s &" % h1.IP())

    h2 = net.get("embedder")
    h2.cmdPrint("telnet 10.0.0.2 12345")

    # CLI(net)
    p1.terminate()
    net.stop()


if __name__ == "__main__":
    # Tell mininet to print useful information
    setLogLevel("info")
    simpleTest()

server.py

from xmlrpc.server import SimpleXMLRPCServer
import socket
import string
import socketserver
import os
import sys
from subprocess import Popen, PIPE

x = int(sys.argv[1])
tries = 0


class SimpleThreadedXMLRPCServer(socketserver.ThreadingMixIn, SimpleXMLRPCServer):
    allow_reuse_address = True


class Functions:
    # var_str = "yyyaaa"

    def guess_number(self, n):
        global tries
        tries = tries + 1
        if n > x:
            msg = "Number is too high"
        if n < x:
            msg = "Number is too low"
        if n == x:
            msg = "You found the number in " + str(tries) + "tries. Congratulations!"
            tries = 0
        return msg

    # def str_get():
    #     return var_str


if __name__ == "__main__":
    port = 8100
    server = SimpleThreadedXMLRPCServer(("", port))
    server.register_instance(Functions())
    print("Serever listening...")
    server.serve_forever()

client.py

import xmlrpc.client as cl



addr = "10.0.0.2"
port = 8100
# rhost = xmlrpclib.Server("http://" + addr + ":" + str(port))
rhost = cl.Server("http://" + addr + ":" + str(port))
# msg = rhost.str_get()
# print(msg)
# inp = ""
print("Guess a number between 1 and 100")
print()
while 1:
    # msg = rhost.str_get()
    # print(msg)

    inp = input(">")
    msg = rhost.guess_number(int(inp))

    print(msg)

if "found" in msg:
    sys.exit(0)

execution of server/client scripts to hosts

host1.sendCmd("python3 server.py")
host2.cmdPrint("python3 client.py")

If I run everything from mininet CLI with different xterm windows working fine but when using the mininet API nothing works properly, I've also tried some different client/server scripts, and sometimes it was working. Actually, it worked only in the first run. So I was thinking maybe there is a way to use subprocess to open xterm windows and then run a command inside xterm with some pipe subprocess. I want everything to be run through a python script, not by hand. Can anyone give me any help?

TassosK
  • 293
  • 3
  • 16

2 Answers2

1

Why not use mininet's python interface to achieve this? From your question it seems like you want to get the names of the nodes that sudo mn creates by default.

In that case why not just add the following to your python:

from mininet.topo import SingleSwitchTopo
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.link import TCLink

if __name__ == '__main__':
    topo = SingleSwitchTopo()
    net = Mininet(topo=topo, host=CPULimitedHost, link=TCLink)

    net.start()

    nodes = net.items()
    node_names, _ = zip(*nodes)

    print(node_names)
    net.stop()

SingleSwitchTopo is the one that mn uses by default (two hosts connected to a single switch). net.items() gives you a tuple of the node's names and ids see here. Perhaps I misunderstand your question, but seems like trying to access it via subprocess when there is an API is overcomplicating an otherwise simple task.

Misho Janev
  • 512
  • 5
  • 13
  • Practically I want to run `host1 xterm` and the run some testing/benchmarks using `xmlrpc` and I want to use the IPS of the hosts from rpc client/servers scripts, from the outside enviroment. The nodes command is just an example I used. – TassosK May 14 '21 at 19:12
  • My goal is to automate the process so I don't need to run it step by step, I want a script to build a mininet topology then run `h1 xterm` and then executing python scripts outside the mininet. – TassosK May 14 '21 at 19:18
  • 1
    You can achieve this by using the method above. Xterm will not be needed as doing a `host.cmd("")` will have the same effect. You can also capture the output of that. Take a look at the API – Misho Janev May 14 '21 at 23:19
  • 1
    I've updated the question with full details, something is wrong with the API nothing working but with CLI things are fine that's why I am thinking of subprocess xterm approach – TassosK May 22 '21 at 13:00
0

Finally, I found what caused the [Errno 111] : connection refused when the client trying to connect to the server. It was something "crazy" in a good way ;).

I just realized that server wasn't ready and running when the client post a request, simply because both execution commands start simultaneously. So, I add a delay between calling/execution cmd lines like this:

host1.sendCmd("python3 server.py")
sleep(5)
host2.cmdPrint("python3 client.py")

Extra comments:

Important to mention that the sendCmd() gives an assertion await error when net.stop() runs. The documentations says to use host1.monitor() after sendCmd() and before net.stop() but it didn't work. So, I replaced the sendCmd() with popen() and then used the terminate() and everything is fine now!

TassosK
  • 293
  • 3
  • 16