initial changes to try and cleanup shell commands used within core

This commit is contained in:
Blake J. Harnden 2018-02-27 10:48:01 -08:00
parent 49a2f77f45
commit 6b8ee13f5d
22 changed files with 185 additions and 291 deletions

View file

@ -282,7 +282,6 @@ class SimpleJailNode(PyCoreNode):
def getaddr(self, ifname, rescan=False): def getaddr(self, ifname, rescan=False):
return None return None
# return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
def addsymlink(self, path, file): def addsymlink(self, path, file):
""" """

View file

@ -988,7 +988,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
upstream = True upstream = True
netif = net2.getlinknetif(net) netif = net2.getlinknetif(net)
if netif is None: if netif is None:
raise ValueError, "modify unknown link between nets" raise ValueError("modify unknown link between nets")
if upstream: if upstream:
netif.swapparams("_params_up") netif.swapparams("_params_up")
net.linkconfig(netif, bw=bw, delay=delay, net.linkconfig(netif, bw=bw, delay=delay,
@ -1087,7 +1087,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
# echo back exec message with cmd for spawning interactive terminal # echo back exec message with cmd for spawning interactive terminal
if command == "bash": if command == "bash":
command = "/bin/bash" command = "/bin/bash"
res = node.termcmdstring(command) res = node.client.termcmdstring(command)
tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res)
reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data) reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data)
return reply, return reply,
@ -1099,7 +1099,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if message.flags & MessageFlags.LOCAL.value: if message.flags & MessageFlags.LOCAL.value:
status, res = utils.cmdresult(shlex.split(command)) status, res = utils.cmdresult(shlex.split(command))
else: else:
status, res = node.cmdresult(shlex.split(command)) status, res = node.client.cmdresult(shlex.split(command))
logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res)) logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res))
if message.flags & MessageFlags.TEXT.value: if message.flags & MessageFlags.TEXT.value:
tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res)
@ -1112,7 +1112,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if message.flags & MessageFlags.LOCAL.value: if message.flags & MessageFlags.LOCAL.value:
utils.mutedetach(shlex.split(command)) utils.mutedetach(shlex.split(command))
else: else:
node.cmd(shlex.split(command), wait=False) node.client.cmd(shlex.split(command), wait=False)
except KeyError: except KeyError:
logger.exception("error getting object: %s", node_num) logger.exception("error getting object: %s", node_num)
# XXX wait and queue this message to try again later # XXX wait and queue this message to try again later

View file

@ -556,7 +556,7 @@ class PyCoreNetIf(object):
""" """
Creates a PyCoreNetIf instance. Creates a PyCoreNetIf instance.
:param node: node for interface :param core.netns.vnode.SimpleLxcNode node: node for interface
:param str name: interface name :param str name: interface name
:param mtu: mtu value :param mtu: mtu value
""" """

View file

@ -912,17 +912,16 @@ class EmaneManager(ConfigurableManager):
# multicast route is needed for OTA data # multicast route is needed for OTA data
cmd = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] cmd = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev]
# rc = node.cmd(cmd, wait=True) node.client.cmd(cmd, wait=True)
node.cmd(cmd, wait=True)
# multicast route is also needed for event data if on control network # multicast route is also needed for event data if on control network
if eventservicenetidx >= 0 and eventgroup != otagroup: if eventservicenetidx >= 0 and eventgroup != otagroup:
cmd = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] cmd = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev]
node.cmd(cmd, wait=True) node.client.cmd(cmd, wait=True)
try: try:
cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)]
logger.info("Emane.startdaemons2() running %s" % str(cmd)) logger.info("Emane.startdaemons2() running %s" % str(cmd))
status, output = node.cmdresult(cmd) status, output = node.client.cmdresult(cmd)
logger.info("Emane.startdaemons2() return code %d" % status) logger.info("Emane.startdaemons2() return code %d" % status)
logger.info("Emane.startdaemons2() output: %s" % output) logger.info("Emane.startdaemons2() output: %s" % output)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
@ -955,7 +954,7 @@ class EmaneManager(ConfigurableManager):
stop_emane_on_host = True stop_emane_on_host = True
continue continue
if node.up: if node.up:
node.cmd(cmd, wait=False) node.client.cmd(cmd, wait=False)
# TODO: RJ45 node # TODO: RJ45 node
else: else:
stop_emane_on_host = True stop_emane_on_host = True
@ -1161,7 +1160,7 @@ class EmaneManager(ConfigurableManager):
if emane.VERSION < emane.EMANE092: if emane.VERSION < emane.EMANE092:
status = subprocess.call(cmd) status = subprocess.call(cmd)
else: else:
status = node.cmd(cmd, wait=True) status = node.client.cmd(cmd, wait=True)
except IOError: except IOError:
logger.exception("error checking if emane is running") logger.exception("error checking if emane is running")

View file

@ -60,7 +60,7 @@ class VEth(PyCoreNetIf):
if not self.up: if not self.up:
return return
if self.node: if self.node:
self.node.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name])
if self.localname: if self.localname:
utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname]) utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname])
self.up = False self.up = False
@ -112,7 +112,7 @@ class TunTap(PyCoreNetIf):
""" """
if not self.up: if not self.up:
return return
self.node.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name])
# if self.name: # if self.name:
# mutedetach(["tunctl", "-d", self.localname]) # mutedetach(["tunctl", "-d", self.localname])
self.up = False self.up = False
@ -169,7 +169,7 @@ class TunTap(PyCoreNetIf):
def nodedevexists(): def nodedevexists():
cmd = (constants.IP_BIN, "link", "show", self.name) cmd = (constants.IP_BIN, "link", "show", self.name)
return self.node.cmd(cmd) return self.node.client.cmd(cmd)
count = 0 count = 0
while True: while True:
@ -206,8 +206,8 @@ class TunTap(PyCoreNetIf):
logger.exception(msg) logger.exception(msg)
return return
self.node.cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) self.node.client.cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name])
self.node.cmd([constants.IP_BIN, "link", "set", self.name, "up"]) self.node.client.cmd([constants.IP_BIN, "link", "set", self.name, "up"])
def setaddrs(self): def setaddrs(self):
""" """
@ -217,7 +217,7 @@ class TunTap(PyCoreNetIf):
""" """
self.waitfordevicenode() self.waitfordevicenode()
for addr in self.addrlist: for addr in self.addrlist:
self.node.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) self.node.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
class GreTap(PyCoreNetIf): class GreTap(PyCoreNetIf):

View file

@ -27,6 +27,14 @@ utils.check_executables([constants.IP_BIN])
class SimpleLxcNode(PyCoreNode): class SimpleLxcNode(PyCoreNode):
""" """
Provides simple lxc functionality for core nodes. Provides simple lxc functionality for core nodes.
:type nodedir: str
:type ctrlchnlname: str
:type client: core.netns.vnodeclient.VnodeClient
:type pid: int
:type up: bool
:type lock: threading.RLock
:type _mounts: list[tuple[str, str]]
""" """
valid_deladdrtype = ("inet", "inet6", "inet6link") valid_deladdrtype = ("inet", "inet6", "inet6link")
@ -43,7 +51,7 @@ class SimpleLxcNode(PyCoreNode):
PyCoreNode.__init__(self, session, objid, name, start=start) PyCoreNode.__init__(self, session, objid, name, start=start)
self.nodedir = nodedir self.nodedir = nodedir
self.ctrlchnlname = os.path.abspath(os.path.join(self.session.session_dir, self.name)) self.ctrlchnlname = os.path.abspath(os.path.join(self.session.session_dir, self.name))
self.vnodeclient = None self.client = None
self.pid = None self.pid = None
self.up = False self.up = False
self.lock = threading.RLock() self.lock = threading.RLock()
@ -100,11 +108,11 @@ class SimpleLxcNode(PyCoreNode):
if tmp.wait(): if tmp.wait():
raise Exception("command failed: %s" % vnoded) raise Exception("command failed: %s" % vnoded)
self.vnodeclient = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname)
logger.info("bringing up loopback interface") logger.info("bringing up loopback interface")
self.cmd([constants.IP_BIN, "link", "set", "lo", "up"]) self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"])
logger.info("setting hostname: %s" % self.name) logger.info("setting hostname: %s" % self.name)
self.cmd(["hostname", self.name]) self.client.cmd(["hostname", self.name])
self.up = True self.up = True
def shutdown(self): def shutdown(self):
@ -142,88 +150,9 @@ class SimpleLxcNode(PyCoreNode):
# clear interface data, close client, and mark self and not up # clear interface data, close client, and mark self and not up
self._netif.clear() self._netif.clear()
self.vnodeclient.close() self.client.close()
self.up = False self.up = False
# TODO: potentially remove all these wrapper methods, just make use of object itself.
def cmd(self, args, wait=True):
"""
Wrapper around vnodeclient cmd.
:param args: arguments for ocmmand
:param wait: wait or not
:return:
"""
return self.vnodeclient.cmd(args, wait)
def cmdresult(self, args):
"""
Wrapper around vnodeclient cmdresult.
:param args: arguments for ocmmand
:return:
"""
return self.vnodeclient.cmdresult(args)
def popen(self, args):
"""
Wrapper around vnodeclient popen.
:param args: arguments for ocmmand
:return:
"""
return self.vnodeclient.popen(args)
def icmd(self, args):
"""
Wrapper around vnodeclient icmd.
:param args: arguments for ocmmand
:return:
"""
return self.vnodeclient.icmd(args)
def redircmd(self, infd, outfd, errfd, args, wait=True):
"""
Wrapper around vnodeclient redircmd.
:param infd: input file descriptor
:param outfd: output file descriptor
:param errfd: err file descriptor
:param args: command arguments
:param wait: wait or not
:return:
"""
return self.vnodeclient.redircmd(infd, outfd, errfd, args, wait)
def term(self, sh="/bin/sh"):
"""
Wrapper around vnodeclient term.
:param sh: shell to create terminal for
:return:
"""
return self.vnodeclient.term(sh=sh)
def termcmdstring(self, sh="/bin/sh"):
"""
Wrapper around vnodeclient termcmdstring.
:param sh: shell to run command in
:return:
"""
return self.vnodeclient.termcmdstring(sh=sh)
def shcmd(self, cmdstr, sh="/bin/sh"):
"""
Wrapper around vnodeclient shcmd.
:param str cmdstr: command string
:param sh: shell to run command in
:return:
"""
return self.vnodeclient.shcmd(cmdstr, sh=sh)
def boot(self): def boot(self):
""" """
Boot logic. Boot logic.
@ -243,9 +172,8 @@ class SimpleLxcNode(PyCoreNode):
source = os.path.abspath(source) source = os.path.abspath(source)
logger.info("mounting %s at %s" % (source, target)) logger.info("mounting %s at %s" % (source, target))
try: try:
shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % ( shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target)
target, constants.MOUNT_BIN, source, target) self.client.shcmd(shcmd)
self.shcmd(shcmd)
self._mounts.append((source, target)) self._mounts.append((source, target))
except IOError: except IOError:
logger.exception("mounting failed for %s at %s", source, target) logger.exception("mounting failed for %s at %s", source, target)
@ -259,7 +187,7 @@ class SimpleLxcNode(PyCoreNode):
""" """
logger.info("unmounting: %s", target) logger.info("unmounting: %s", target)
try: try:
self.cmd([constants.UMOUNT_BIN, "-n", "-l", target]) self.client.cmd([constants.UMOUNT_BIN, "-n", "-l", target])
except IOError: except IOError:
logger.exception("unmounting failed for %s" % target) logger.exception("unmounting failed for %s" % target)
@ -307,14 +235,14 @@ class SimpleLxcNode(PyCoreNode):
if self.up: if self.up:
subprocess.check_call([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) subprocess.check_call([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
self.cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) self.client.cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
veth.name = ifname veth.name = ifname
if self.up: if self.up:
# TODO: potentially find better way to query interface ID # TODO: potentially find better way to query interface ID
# retrieve interface information # retrieve interface information
result, output = self.cmdresult(["ip", "link", "show", veth.name]) result, output = self.client.cmdresult(["ip", "link", "show", veth.name])
logger.info("interface command output: %s", output) logger.info("interface command output: %s", output)
output = output.split("\n") output = output.split("\n")
veth.flow_id = int(output[0].strip().split(":")[0]) + 1 veth.flow_id = int(output[0].strip().split(":")[0]) + 1
@ -375,8 +303,8 @@ class SimpleLxcNode(PyCoreNode):
""" """
self._netif[ifindex].sethwaddr(addr) self._netif[ifindex].sethwaddr(addr)
if self.up: if self.up:
(status, result) = self.cmdresult([constants.IP_BIN, "link", "set", "dev", (status, result) = self.client.cmdresult([constants.IP_BIN, "link", "set", "dev",
self.ifname(ifindex), "address", str(addr)]) self.ifname(ifindex), "address", str(addr)])
if status: if status:
logger.error("error setting MAC address %s", str(addr)) logger.error("error setting MAC address %s", str(addr))
@ -390,11 +318,11 @@ class SimpleLxcNode(PyCoreNode):
""" """
if self.up: if self.up:
if ":" in str(addr): # check if addr is ipv6 if ":" in str(addr): # check if addr is ipv6
self.cmd([constants.IP_BIN, "addr", "add", str(addr), self.client.cmd([constants.IP_BIN, "addr", "add", str(addr),
"dev", self.ifname(ifindex)]) "dev", self.ifname(ifindex)])
else: else:
self.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+",
"dev", self.ifname(ifindex)]) "dev", self.ifname(ifindex)])
self._netif[ifindex].addaddr(addr) self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr): def deladdr(self, ifindex, addr):
@ -411,7 +339,7 @@ class SimpleLxcNode(PyCoreNode):
logger.exception("trying to delete unknown address: %s" % addr) logger.exception("trying to delete unknown address: %s" % addr)
if self.up: if self.up:
self.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) self.client.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
def delalladdr(self, ifindex, addrtypes=valid_deladdrtype): def delalladdr(self, ifindex, addrtypes=valid_deladdrtype):
""" """
@ -438,7 +366,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing :return: nothing
""" """
if self.up: if self.up:
self.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) self.client.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"])
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
""" """
@ -503,13 +431,12 @@ class SimpleLxcNode(PyCoreNode):
"type", "veth", "peer", "name", tmp2]) "type", "veth", "peer", "name", tmp2])
subprocess.call([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) subprocess.call([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)])
self.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) self.client.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname])
self.addnetif(PyCoreNetIf(self, ifname), self.newifindex()) self.addnetif(PyCoreNetIf(self, ifname), self.newifindex())
subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)])
othernode.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) othernode.client.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname])
othernode.addnetif(PyCoreNetIf(othernode, otherifname), othernode.addnetif(PyCoreNetIf(othernode, otherifname), othernode.newifindex())
othernode.newifindex())
def addfile(self, srcname, filename): def addfile(self, srcname, filename):
""" """
@ -520,7 +447,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing :return: nothing
""" """
shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename) shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename)
self.shcmd(shcmd) self.client.shcmd(shcmd)
def getaddr(self, ifname, rescan=False): def getaddr(self, ifname, rescan=False):
""" """
@ -530,7 +457,7 @@ class SimpleLxcNode(PyCoreNode):
:param bool rescan: rescan flag :param bool rescan: rescan flag
:return: :return:
""" """
return self.vnodeclient.getaddr(ifname=ifname, rescan=rescan) return self.client.getaddr(ifname=ifname, rescan=rescan)
def netifstats(self, ifname=None): def netifstats(self, ifname=None):
""" """
@ -539,7 +466,7 @@ class SimpleLxcNode(PyCoreNode):
:param str ifname: interface name to get state for :param str ifname: interface name to get state for
:return: :return:
""" """
return self.vnodeclient.netifstats(ifname=ifname) return self.client.netifstats(ifname=ifname)
class LxcNode(SimpleLxcNode): class LxcNode(SimpleLxcNode):

View file

@ -6,17 +6,12 @@ by invoking the vcmd shell command.
""" """
import os import os
import stat
import subprocess import vcmd
from core import constants from core import constants
from core import logger from core import logger
USE_VCMD_MODULE = True
if USE_VCMD_MODULE:
import vcmd
VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd") VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd")
@ -34,12 +29,19 @@ class VnodeClient(object):
""" """
self.name = name self.name = name
self.ctrlchnlname = ctrlchnlname self.ctrlchnlname = ctrlchnlname
if USE_VCMD_MODULE: self.cmdchnl = vcmd.VCmd(self.ctrlchnlname)
self.cmdchnl = vcmd.VCmd(self.ctrlchnlname)
else:
self.cmdchnl = None
self._addr = {} self._addr = {}
def _verify_connection(self):
"""
Checks that the vcmd client is properly connected.
:return: nothing
:raises ValueError: when not connected
"""
if not self.connected():
raise ValueError("vcmd not connected")
def connected(self): def connected(self):
""" """
Check if node is connected or not. Check if node is connected or not.
@ -47,10 +49,7 @@ class VnodeClient(object):
:return: True if connected, False otherwise :return: True if connected, False otherwise
:rtype: bool :rtype: bool
""" """
if USE_VCMD_MODULE: return self.cmdchnl.connected()
return self.cmdchnl.connected()
else:
return True
def close(self): def close(self):
""" """
@ -58,8 +57,7 @@ class VnodeClient(object):
:return: nothing :return: nothing
""" """
if USE_VCMD_MODULE: self.cmdchnl.close()
self.cmdchnl.close()
def cmd(self, args, wait=True): def cmd(self, args, wait=True):
""" """
@ -70,24 +68,16 @@ class VnodeClient(object):
:return: command status :return: command status
:rtype: int :rtype: int
""" """
if USE_VCMD_MODULE: self._verify_connection()
if not self.cmdchnl.connected():
raise ValueError("self.cmdchnl not connected") # TODO: clean this up after checking return value for qcmd
tmp = self.cmdchnl.qcmd(args) tmp = self.cmdchnl.qcmd(args)
if not wait: if not wait:
return tmp return tmp
tmp = tmp.wait() tmp = tmp.wait()
else:
if wait:
mode = os.P_WAIT
else:
mode = os.P_NOWAIT
tmp = os.spawnlp(mode, VCMD, VCMD, "-c", self.ctrlchnlname, "-q", "--", *args)
if not wait:
return tmp
if tmp: if tmp:
logger.warn("cmd exited with status %s: %s" % (tmp, str(args))) logger.warn("cmd exited with status %s: %s", tmp, args)
return tmp return tmp
@ -101,14 +91,16 @@ class VnodeClient(object):
:return: command status and combined stdout and stderr output :return: command status and combined stdout and stderr output
:rtype: tuple[int, str] :rtype: tuple[int, str]
""" """
cmdid, cmdin, cmdout, cmderr = self.popen(args) self._verify_connection()
result = cmdout.read()
result += cmderr.read() p, stdin, stdout, stderr = self.popen(args)
cmdin.close() output = stdout.read() + stderr.read()
cmdout.close() stdin.close()
cmderr.close() stdout.close()
status = cmdid.wait() stderr.close()
return status, result status = p.wait()
return status, output
def popen(self, args): def popen(self, args):
""" """
@ -118,15 +110,8 @@ class VnodeClient(object):
:return: popen object, stdin, stdout, and stderr :return: popen object, stdin, stdout, and stderr
:rtype: tuple :rtype: tuple
""" """
if USE_VCMD_MODULE: self._verify_connection()
if not self.cmdchnl.connected(): return self.cmdchnl.popen(args)
raise ValueError("self.cmdchnl not connected")
return self.cmdchnl.popen(args)
else:
cmd = [VCMD, "-c", self.ctrlchnlname, "--"]
cmd.extend(args)
tmp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return tmp, tmp.stdin, tmp.stdout, tmp.stderr
def icmd(self, args): def icmd(self, args):
""" """
@ -151,18 +136,20 @@ class VnodeClient(object):
:return: command status :return: command status
:rtype: int :rtype: int
""" """
if not USE_VCMD_MODULE: self._verify_connection()
raise NotImplementedError
if not self.cmdchnl.connected(): # TODO: clean this up after verifying redircmd return values
raise ValueError("self.cmdchnl not connected")
tmp = self.cmdchnl.redircmd(infd, outfd, errfd, args) tmp = self.cmdchnl.redircmd(infd, outfd, errfd, args)
if not wait: if not wait:
return tmp return tmp
tmp = tmp.wait() tmp = tmp.wait()
if tmp: if tmp:
logger.warn("cmd exited with status %s: %s" % (tmp, str(args))) logger.warn("cmd exited with status %s: %s", tmp, args)
return tmp return tmp
# TODO: validate if this is ever used
def term(self, sh="/bin/sh"): def term(self, sh="/bin/sh"):
""" """
Open a terminal on a node. Open a terminal on a node.
@ -171,8 +158,7 @@ class VnodeClient(object):
:return: terminal command result :return: terminal command result
:rtype: int :rtype: int
""" """
cmd = ("xterm", "-ut", "-title", self.name, "-e", cmd = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh)
VCMD, "-c", self.ctrlchnlname, "--", sh)
if "SUDO_USER" in os.environ: if "SUDO_USER" in os.environ:
cmd = ("su", "-s", "/bin/sh", "-c", cmd = ("su", "-s", "/bin/sh", "-c",
"exec " + " ".join(map(lambda x: "'%s'" % x, cmd)), "exec " + " ".join(map(lambda x: "'%s'" % x, cmd)),
@ -210,35 +196,36 @@ class VnodeClient(object):
""" """
if ifname in self._addr and not rescan: if ifname in self._addr and not rescan:
return self._addr[ifname] return self._addr[ifname]
tmp = {"ether": [], "inet": [], "inet6": [], "inet6link": []}
cmd = [constants.IP_BIN, "addr", "show", "dev", ifname]
cmdid, cmdin, cmdout, cmderr = self.popen(cmd)
cmdin.close()
for line in cmdout: interface = {"ether": [], "inet": [], "inet6": [], "inet6link": []}
cmd = [constants.IP_BIN, "addr", "show", "dev", ifname]
p, stdin, stdout, stderr = self.popen(cmd)
stdin.close()
for line in stdout:
line = line.strip().split() line = line.strip().split()
if line[0] == "link/ether": if line[0] == "link/ether":
tmp["ether"].append(line[1]) interface["ether"].append(line[1])
elif line[0] == "inet": elif line[0] == "inet":
tmp["inet"].append(line[1]) interface["inet"].append(line[1])
elif line[0] == "inet6": elif line[0] == "inet6":
if line[3] == "global": if line[3] == "global":
tmp["inet6"].append(line[1]) interface["inet6"].append(line[1])
elif line[3] == "link": elif line[3] == "link":
tmp["inet6link"].append(line[1]) interface["inet6link"].append(line[1])
else: else:
logger.warn("unknown scope: %s" % line[3]) logger.warn("unknown scope: %s" % line[3])
err = cmderr.read() err = stderr.read()
cmdout.close() stdout.close()
cmderr.close() stderr.close()
status = cmdid.wait() status = p.wait()
if status: if status:
logger.warn("nonzero exist status (%s) for cmd: %s" % (status, cmd)) logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd)
if err: if err:
logger.warn("error output: %s" % err) logger.warn("error output: %s", err)
self._addr[ifname] = tmp self._addr[ifname] = interface
return tmp return interface
def netifstats(self, ifname=None): def netifstats(self, ifname=None):
""" """
@ -250,15 +237,15 @@ class VnodeClient(object):
""" """
stats = {} stats = {}
cmd = ["cat", "/proc/net/dev"] cmd = ["cat", "/proc/net/dev"]
cmdid, cmdin, cmdout, cmderr = self.popen(cmd) p, stdin, stdout, stderr = self.popen(cmd)
cmdin.close() stdin.close()
# ignore first line # ignore first line
cmdout.readline() stdout.readline()
# second line has count names # second line has count names
tmp = cmdout.readline().strip().split("|") tmp = stdout.readline().strip().split("|")
rxkeys = tmp[1].split() rxkeys = tmp[1].split()
txkeys = tmp[2].split() txkeys = tmp[2].split()
for line in cmdout: for line in stdout:
line = line.strip().split() line = line.strip().split()
devname, tmp = line[0].split(":") devname, tmp = line[0].split(":")
if tmp: if tmp:
@ -271,53 +258,15 @@ class VnodeClient(object):
for count in txkeys: for count in txkeys:
stats[devname]["tx"][count] = int(line[field]) stats[devname]["tx"][count] = int(line[field])
field += 1 field += 1
err = cmderr.read() err = stderr.read()
cmdout.close() stdout.close()
cmderr.close() stderr.close()
status = cmdid.wait() status = p.wait()
if status: if status:
logger.warn("nonzero exist status (%s) for cmd: %s" % (status, cmd)) logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd)
if err: if err:
logger.warn("error output: %s" % err) logger.warn("error output: %s", err)
if ifname is not None: if ifname is not None:
return stats[ifname] return stats[ifname]
else: else:
return stats return stats
def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None):
"""
Create clients
:param str sessiondir: session directory to create clients
:param class clientcls: class to create clients from
:param func cmdchnlfilterfunc: command channel filter function
:return: list of created clients
:rtype: list
"""
direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir))
cmdchnls = filter(lambda x: stat.S_ISSOCK(os.stat(x).st_mode), direntries)
if cmdchnlfilterfunc:
cmdchnls = filter(cmdchnlfilterfunc, cmdchnls)
cmdchnls.sort()
return map(lambda x: clientcls(os.path.basename(x), x), cmdchnls)
def createremoteclients(sessiondir, clientcls=VnodeClient, filterfunc=None):
"""
Creates remote VnodeClients, for nodes emulated on other machines. The
session.Broker writes a n1.conf/server file having the server's info.
:param str sessiondir: session directory to create clients
:param class clientcls: class to create clients from
:param func filterfunc: filter function
:return: list of remove clients
:rtype: list
"""
direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir))
nodedirs = filter(lambda x: stat.S_ISDIR(os.stat(x).st_mode), direntries)
nodedirs = filter(lambda x: os.path.exists(os.path.join(x, "server")), nodedirs)
if filterfunc:
nodedirs = filter(filterfunc, nodedirs)
nodedirs.sort()
return map(lambda x: clientcls(x), nodedirs)

View file

@ -312,7 +312,7 @@ class CoreServices(ConfigurableManager):
for cmd in service.getstartup(node, services): for cmd in service.getstartup(node, services):
try: try:
# NOTE: this wait=False can be problematic! # NOTE: this wait=False can be problematic!
node.cmd(shlex.split(cmd), wait=False) node.client.cmd(shlex.split(cmd), wait=False)
except: except:
logger.exception("error starting command %s", cmd) logger.exception("error starting command %s", cmd)
@ -358,7 +358,7 @@ class CoreServices(ConfigurableManager):
for cmd in service._startup: for cmd in service._startup:
try: try:
# NOTE: this wait=False can be problematic! # NOTE: this wait=False can be problematic!
node.cmd(shlex.split(cmd), wait=False) node.client.cmd(shlex.split(cmd), wait=False)
except: except:
logger.exception("error starting command %s", cmd) logger.exception("error starting command %s", cmd)
@ -417,7 +417,7 @@ class CoreServices(ConfigurableManager):
for cmd in validate_cmds: for cmd in validate_cmds:
logger.info("validating service %s using: %s", service._name, cmd) logger.info("validating service %s using: %s", service._name, cmd)
try: try:
status, result = node.cmdresult(shlex.split(cmd)) status, result = node.client.cmdresult(shlex.split(cmd))
if status != 0: if status != 0:
raise ValueError("non-zero exit status") raise ValueError("non-zero exit status")
except: except:
@ -453,7 +453,7 @@ class CoreServices(ConfigurableManager):
else: else:
for cmd in service._shutdown: for cmd in service._shutdown:
try: try:
tmp = node.cmd(shlex.split(cmd), wait=True) tmp = node.client.cmd(shlex.split(cmd), wait=True)
status += "%s" % tmp status += "%s" % tmp
except: except:
logger.exception("error running stop command %s", cmd) logger.exception("error running stop command %s", cmd)
@ -766,7 +766,7 @@ class CoreServices(ConfigurableManager):
for cmd in cmds: for cmd in cmds:
try: try:
# node.cmd(shlex.split(cmd), wait = False) # node.cmd(shlex.split(cmd), wait = False)
status = node.cmd(shlex.split(cmd), wait=True) status = node.client.cmd(shlex.split(cmd), wait=True)
if status != 0: if status != 0:
fail += "Start %s(%s)," % (s._name, cmd) fail += "Start %s(%s)," % (s._name, cmd)
except: except:

View file

@ -610,6 +610,7 @@ class Session(object):
:param int object_id: object id to retrieve :param int object_id: object id to retrieve
:return: object for the given id :return: object for the given id
:rtype: core.netns.vnode.SimpleLxcNode
""" """
if object_id not in self.objects: if object_id not in self.objects:
raise KeyError("unknown object id %s" % object_id) raise KeyError("unknown object id %s" % object_id)
@ -1257,7 +1258,7 @@ class Session(object):
utils.mutedetach(commands) utils.mutedetach(commands)
else: else:
node = self.get_object(node_id) node = self.get_object(node_id)
node.cmd(commands, wait=False) node.client.cmd(commands, wait=False)
def send_objects(self): def send_objects(self):
""" """

View file

@ -59,7 +59,7 @@ def test(options):
# launches terminal for the first node # launches terminal for the first node
# n[0].term("bash") # n[0].term("bash")
n[0].icmd(["ping", "-c", "5", "127.0.0.1"]) n[0].client.icmd(["ping", "-c", "5", "127.0.0.1"])
# wait for rate seconds to allow ebtables commands to commit # wait for rate seconds to allow ebtables commands to commit
time.sleep(EbtablesQueue.rate) time.sleep(EbtablesQueue.rate)

View file

@ -82,7 +82,7 @@ def main():
for i in xrange(1, num_local + 1): for i in xrange(1, num_local + 1):
node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i)
node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) node.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
node.setposition(x=150 * i, y=150) node.setposition(x=150 * i, y=150)
n.append(node) n.append(node)

View file

@ -84,7 +84,7 @@ def main():
tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i,
objid=i) objid=i)
tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
tmp.setposition(x=150 * i, y=150) tmp.setposition(x=150 * i, y=150)
session.services.addservicestonode(tmp, "", services_str) session.services.addservicestonode(tmp, "", services_str)
n.append(tmp) n.append(tmp)

View file

@ -159,7 +159,7 @@ def main():
try: try:
n = session.add_object(cls=nodes.LxcNode, name="n%d" % i) n = session.add_object(cls=nodes.LxcNode, name="n%d" % i)
n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) n.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
if options.services is not None: if options.services is not None:
session.services.addservicestonode(n, "", options.services) session.services.addservicestonode(n, "", options.services)
n.boot() n.boot()

View file

@ -19,7 +19,7 @@ import optparse
import sys import sys
from core import constants from core import constants
from core.misc import ipaddress from core.misc import ipaddress
from core.netns import nodes from core.netns import nodes
# node list (count from 1) # node list (count from 1)
@ -72,9 +72,9 @@ def main():
prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i) prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i)
right = session.add_object(cls=nodes.PtpNet) right = session.add_object(cls=nodes.PtpNet)
tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)]) tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"])
tmp.setposition(x=100 * i, y=150) tmp.setposition(x=100 * i, y=150)
n.append(tmp) n.append(tmp)
left = right left = right

View file

@ -16,6 +16,7 @@ import time
from string import Template from string import Template
from core.constants import QUAGGA_STATE_DIR from core.constants import QUAGGA_STATE_DIR
from core.misc import ipaddress from core.misc import ipaddress
from core.misc.utils import mutecall from core.misc.utils import mutecall
from core.netns import nodes from core.netns import nodes
@ -267,7 +268,7 @@ class ManetExperiment(object):
self.nodes[i].boot() self.nodes[i].boot()
# run the boot.sh script on all nodes to start Quagga # run the boot.sh script on all nodes to start Quagga
for i in xrange(numnodes): for i in xrange(numnodes):
self.nodes[i].cmd(["./%s" % self.nodes[i].bootsh]) self.nodes[i].client.cmd(["./%s" % self.nodes[i].bootsh])
def compareroutes(self, node, kr, zr): def compareroutes(self, node, kr, zr):
""" Compare two lists of Route objects. """ Compare two lists of Route objects.
@ -386,7 +387,7 @@ class Cmd:
def open(self): def open(self):
""" Exceute call to node.popen(). """ """ Exceute call to node.popen(). """
self.id, self.stdin, self.out, self.err = \ self.id, self.stdin, self.out, self.err = \
self.node.popen(self.args) self.node.client.popen(self.args)
def parse(self): def parse(self):
""" This method is overloaded by child classes and should return some """ This method is overloaded by child classes and should return some
@ -409,7 +410,7 @@ class VtyshCmd(Cmd):
def open(self): def open(self):
args = ("vtysh", "-c", self.args) args = ("vtysh", "-c", self.args)
self.id, self.stdin, self.out, self.err = self.node.popen(args) self.id, self.stdin, self.out, self.err = self.node.client.popen(args)
class Ospf6NeighState(VtyshCmd): class Ospf6NeighState(VtyshCmd):

View file

@ -57,7 +57,7 @@ def main():
for i in xrange(1, options.numnodes + 1): for i in xrange(1, options.numnodes + 1):
tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i)
tmp.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) tmp.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
tmp.setposition(x=150 * i, y=150) tmp.setposition(x=150 * i, y=150)
n.append(tmp) n.append(tmp)

View file

@ -36,9 +36,9 @@ def test(numnodes, testsec):
tmp = session.add_object(cls=nodes.LxcNode, name="n%d" % i) tmp = session.add_object(cls=nodes.LxcNode, name="n%d" % i)
tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
n.append(tmp) n.append(tmp)
n[0].cmd(["iperf", "-s", "-D"]) n[0].client.cmd(["iperf", "-s", "-D"])
n[-1].icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))])
n[0].cmd(["killall", "-9", "iperf"]) n[0].client.cmd(["killall", "-9", "iperf"])
raw_input("press enter to exit") raw_input("press enter to exit")
session.shutdown() session.shutdown()

View file

@ -131,7 +131,7 @@ class Cmd(object):
def open(self): def open(self):
""" Exceute call to node.popen(). """ """ Exceute call to node.popen(). """
self.id, self.stdin, self.out, self.err = self.node.popen(self.args) self.id, self.stdin, self.out, self.err = self.node.client.popen(self.args)
def parse(self): def parse(self):
""" This method is overloaded by child classes and should return some """ This method is overloaded by child classes and should return some
@ -166,7 +166,7 @@ class ClientServerCmd(Cmd):
self.client_open() # client self.client_open() # client
status = self.client_id.wait() status = self.client_id.wait()
# stop the server # stop the server
self.node.cmdresult(["killall", self.args[0]]) self.node.client.cmdresult(["killall", self.args[0]])
r = self.parse() r = self.parse()
self.cleanup() self.cleanup()
return r return r
@ -174,7 +174,7 @@ class ClientServerCmd(Cmd):
def client_open(self): def client_open(self):
""" Exceute call to client_node.popen(). """ """ Exceute call to client_node.popen(). """
self.client_id, self.client_stdin, self.client_out, self.client_err = \ self.client_id, self.client_stdin, self.client_out, self.client_err = \
self.client_node.popen(self.client_args) self.client_node.client.popen(self.client_args)
def parse(self): def parse(self):
""" This method is overloaded by child classes and should return some """ This method is overloaded by child classes and should return some
@ -207,7 +207,7 @@ class PingCmd(Cmd):
def run(self): def run(self):
if self.verbose: if self.verbose:
self.info("%s initial test ping (max 1 second)..." % self.node.name) self.info("%s initial test ping (max 1 second)..." % self.node.name)
(status, result) = self.node.cmdresult(["ping", "-q", "-c", "1", "-w", "1", self.addr]) (status, result) = self.node.client.cmdresult(["ping", "-q", "-c", "1", "-w", "1", self.addr])
if status != 0: if status != 0:
self.warn("initial ping from %s to %s failed! result:\n%s" % self.warn("initial ping from %s to %s failed! result:\n%s" %
(self.node.name, self.addr, result)) (self.node.name, self.addr, result))
@ -487,13 +487,13 @@ class Experiment(object):
if i > 1: if i > 1:
neigh_left = "%s" % prefix.addr(i - 1) neigh_left = "%s" % prefix.addr(i - 1)
cmd = routecmd + [neigh_left, "dev", node.netif(0).name] cmd = routecmd + [neigh_left, "dev", node.netif(0).name]
(status, result) = node.cmdresult(cmd) (status, result) = node.client.cmdresult(cmd)
if status != 0: if status != 0:
self.warn("failed to add interface route: %s" % cmd) self.warn("failed to add interface route: %s" % cmd)
if i < numnodes: if i < numnodes:
neigh_right = "%s" % prefix.addr(i + 1) neigh_right = "%s" % prefix.addr(i + 1)
cmd = routecmd + [neigh_right, "dev", node.netif(0).name] cmd = routecmd + [neigh_right, "dev", node.netif(0).name]
(status, result) = node.cmdresult(cmd) (status, result) = node.client.cmdresult(cmd)
if status != 0: if status != 0:
self.warn("failed to add interface route: %s" % cmd) self.warn("failed to add interface route: %s" % cmd)
@ -507,7 +507,7 @@ class Experiment(object):
else: else:
gw = neigh_right gw = neigh_right
cmd = routecmd + [addr, "via", gw] cmd = routecmd + [addr, "via", gw]
(status, result) = node.cmdresult(cmd) (status, result) = node.client.cmdresult(cmd)
if status != 0: if status != 0:
self.warn("failed to add route: %s" % cmd) self.warn("failed to add route: %s" % cmd)
@ -635,8 +635,8 @@ class Experiment(object):
if self.verbose: if self.verbose:
self.info("%s initial test ping (max 1 second)..." % \ self.info("%s initial test ping (max 1 second)..." % \
self.firstnode.name) self.firstnode.name)
(status, result) = self.firstnode.cmdresult(["ping", "-q", "-c", "1", (status, result) = self.firstnode.client.cmdresult(["ping", "-q", "-c", "1",
"-w", "1", self.lastaddr]) "-w", "1", self.lastaddr])
if status != 0: if status != 0:
self.warn("initial ping from %s to %s failed! result:\n%s" % \ self.warn("initial ping from %s to %s failed! result:\n%s" % \
(self.firstnode.name, self.lastaddr, result)) (self.firstnode.name, self.lastaddr, result))

View file

@ -37,9 +37,9 @@ def test(numnodes, testsec):
tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
n.append(tmp) n.append(tmp)
net.link(n[0].netif(0), n[-1].netif(0)) net.link(n[0].netif(0), n[-1].netif(0))
n[0].cmd(["iperf", "-s", "-D"]) n[0].client.cmd(["iperf", "-s", "-D"])
n[-1].icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))])
n[0].cmd(["killall", "-9", "iperf"]) n[0].client.cmd(["killall", "-9", "iperf"])
session.shutdown() session.shutdown()

View file

@ -186,18 +186,18 @@ class Core(object):
def ping(self, from_name, to_name): def ping(self, from_name, to_name):
from_node = self.nodes[from_name] from_node = self.nodes[from_name]
to_ip = str(self.get_ip(to_name)) to_ip = str(self.get_ip(to_name))
return from_node.cmd(["ping", "-c", "3", to_ip]) return from_node.client.cmd(["ping", "-c", "3", to_ip])
def ping_output(self, from_name, to_name): def ping_output(self, from_name, to_name):
from_node = self.nodes[from_name] from_node = self.nodes[from_name]
to_ip = str(self.get_ip(to_name)) to_ip = str(self.get_ip(to_name))
vcmd, stdin, stdout, stderr = from_node.popen(["ping", "-i", "0.05", "-c", "3", to_ip]) vcmd, stdin, stdout, stderr = from_node.client.popen(["ping", "-i", "0.05", "-c", "3", to_ip])
return stdout.read().strip() return stdout.read().strip()
def iping(self, from_name, to_name): def iping(self, from_name, to_name):
from_node = self.nodes[from_name] from_node = self.nodes[from_name]
to_ip = str(self.get_ip(to_name)) to_ip = str(self.get_ip(to_name))
from_node.icmd(["ping", "-i", "0.01", "-c", "10", to_ip]) from_node.client.icmd(["ping", "-i", "0.01", "-c", "10", to_ip])
def iperf(self, from_name, to_name): def iperf(self, from_name, to_name):
from_node = self.nodes[from_name] from_node = self.nodes[from_name]
@ -205,9 +205,9 @@ class Core(object):
to_ip = str(self.get_ip(to_name)) to_ip = str(self.get_ip(to_name))
# run iperf server, run client, kill iperf server # run iperf server, run client, kill iperf server
vcmd, stdin, stdout, stderr = to_node.popen(["iperf", "-s", "-u", "-y", "C"]) vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"])
from_node.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) from_node.client.cmd(["iperf", "-u", "-t", "5", "-c", to_ip])
to_node.cmd(["killall", "-9", "iperf"]) to_node.client.cmd(["killall", "-9", "iperf"])
return stdout.read().strip() return stdout.read().strip()

View file

@ -3,13 +3,12 @@ Unit tests for testing basic CORE networks.
""" """
import os import os
import stat
import threading import threading
import time import time
import pytest
from xml.etree import ElementTree from xml.etree import ElementTree
import pytest
from mock import MagicMock from mock import MagicMock
from conftest import EMANE_SERVICES from conftest import EMANE_SERVICES
@ -18,6 +17,7 @@ from core.enumerations import MessageFlags
from core.mobility import BasicRangeModel from core.mobility import BasicRangeModel
from core.netns import nodes from core.netns import nodes
from core.netns import vnodeclient from core.netns import vnodeclient
from core.netns.vnodeclient import VnodeClient
from core.phys.pnodes import PhysicalNode from core.phys.pnodes import PhysicalNode
from core.service import ServiceManager from core.service import ServiceManager
from core.xml import xmlsession from core.xml import xmlsession
@ -29,6 +29,24 @@ _XML_VERSIONS = ["0.0", "1.0"]
_NODE_CLASSES = [nodes.PtpNet, nodes.HubNode, nodes.SwitchNode] _NODE_CLASSES = [nodes.PtpNet, nodes.HubNode, nodes.SwitchNode]
def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None):
"""
Create clients
:param str sessiondir: session directory to create clients
:param class clientcls: class to create clients from
:param func cmdchnlfilterfunc: command channel filter function
:return: list of created clients
:rtype: list
"""
direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir))
cmdchnls = filter(lambda x: stat.S_ISSOCK(os.stat(x).st_mode), direntries)
if cmdchnlfilterfunc:
cmdchnls = filter(cmdchnlfilterfunc, cmdchnls)
cmdchnls.sort()
return map(lambda x: clientcls(os.path.basename(x), x), cmdchnls)
class TestCore: class TestCore:
def test_import_service(self, core): def test_import_service(self, core):
""" """
@ -145,7 +163,7 @@ class TestCore:
# get node client for testing # get node client for testing
n1 = core.get_node("n1") n1 = core.get_node("n1")
client = n1.vnodeclient client = n1.client
# instantiate session # instantiate session
core.session.instantiate() core.session.instantiate()
@ -178,7 +196,7 @@ class TestCore:
assert not client.shcmd(command[0]) assert not client.shcmd(command[0])
# check module methods # check module methods
assert vnodeclient.createclients(core.session.session_dir) assert createclients(core.session.session_dir)
# check convenience methods for interface information # check convenience methods for interface information
assert client.getaddr("eth0") assert client.getaddr("eth0")

View file

@ -47,7 +47,7 @@ Here are the basic elements of a CORE Python script:
node1.newnetif(hub1, ["10.0.0.1/24"]) node1.newnetif(hub1, ["10.0.0.1/24"])
node2.newnetif(hub1, ["10.0.0.2/24"]) node2.newnetif(hub1, ["10.0.0.2/24"])
node1.icmd(["ping", "-c", "5", "10.0.0.2"]) node1.vnodeclient.icmd(["ping", "-c", "5", "10.0.0.2"])
session.shutdown() session.shutdown()