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):
return None
# return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
def addsymlink(self, path, file):
"""

View file

@ -988,7 +988,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
upstream = True
netif = net2.getlinknetif(net)
if netif is None:
raise ValueError, "modify unknown link between nets"
raise ValueError("modify unknown link between nets")
if upstream:
netif.swapparams("_params_up")
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
if command == "bash":
command = "/bin/bash"
res = node.termcmdstring(command)
res = node.client.termcmdstring(command)
tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res)
reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data)
return reply,
@ -1099,7 +1099,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if message.flags & MessageFlags.LOCAL.value:
status, res = utils.cmdresult(shlex.split(command))
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))
if message.flags & MessageFlags.TEXT.value:
tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res)
@ -1112,7 +1112,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if message.flags & MessageFlags.LOCAL.value:
utils.mutedetach(shlex.split(command))
else:
node.cmd(shlex.split(command), wait=False)
node.client.cmd(shlex.split(command), wait=False)
except KeyError:
logger.exception("error getting object: %s", node_num)
# XXX wait and queue this message to try again later

View file

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

View file

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

View file

@ -60,7 +60,7 @@ class VEth(PyCoreNetIf):
if not self.up:
return
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:
utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname])
self.up = False
@ -112,7 +112,7 @@ class TunTap(PyCoreNetIf):
"""
if not self.up:
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:
# mutedetach(["tunctl", "-d", self.localname])
self.up = False
@ -169,7 +169,7 @@ class TunTap(PyCoreNetIf):
def nodedevexists():
cmd = (constants.IP_BIN, "link", "show", self.name)
return self.node.cmd(cmd)
return self.node.client.cmd(cmd)
count = 0
while True:
@ -206,8 +206,8 @@ class TunTap(PyCoreNetIf):
logger.exception(msg)
return
self.node.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.localname, "name", self.name])
self.node.client.cmd([constants.IP_BIN, "link", "set", self.name, "up"])
def setaddrs(self):
"""
@ -217,7 +217,7 @@ class TunTap(PyCoreNetIf):
"""
self.waitfordevicenode()
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):

View file

@ -27,6 +27,14 @@ utils.check_executables([constants.IP_BIN])
class SimpleLxcNode(PyCoreNode):
"""
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")
@ -43,7 +51,7 @@ class SimpleLxcNode(PyCoreNode):
PyCoreNode.__init__(self, session, objid, name, start=start)
self.nodedir = nodedir
self.ctrlchnlname = os.path.abspath(os.path.join(self.session.session_dir, self.name))
self.vnodeclient = None
self.client = None
self.pid = None
self.up = False
self.lock = threading.RLock()
@ -100,11 +108,11 @@ class SimpleLxcNode(PyCoreNode):
if tmp.wait():
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")
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)
self.cmd(["hostname", self.name])
self.client.cmd(["hostname", self.name])
self.up = True
def shutdown(self):
@ -142,88 +150,9 @@ class SimpleLxcNode(PyCoreNode):
# clear interface data, close client, and mark self and not up
self._netif.clear()
self.vnodeclient.close()
self.client.close()
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):
"""
Boot logic.
@ -243,9 +172,8 @@ class SimpleLxcNode(PyCoreNode):
source = os.path.abspath(source)
logger.info("mounting %s at %s" % (source, target))
try:
shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (
target, constants.MOUNT_BIN, source, target)
self.shcmd(shcmd)
shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target)
self.client.shcmd(shcmd)
self._mounts.append((source, target))
except IOError:
logger.exception("mounting failed for %s at %s", source, target)
@ -259,7 +187,7 @@ class SimpleLxcNode(PyCoreNode):
"""
logger.info("unmounting: %s", target)
try:
self.cmd([constants.UMOUNT_BIN, "-n", "-l", target])
self.client.cmd([constants.UMOUNT_BIN, "-n", "-l", target])
except IOError:
logger.exception("unmounting failed for %s" % target)
@ -307,14 +235,14 @@ class SimpleLxcNode(PyCoreNode):
if self.up:
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
if self.up:
# TODO: potentially find better way to query interface ID
# 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)
output = output.split("\n")
veth.flow_id = int(output[0].strip().split(":")[0]) + 1
@ -375,8 +303,8 @@ class SimpleLxcNode(PyCoreNode):
"""
self._netif[ifindex].sethwaddr(addr)
if self.up:
(status, result) = self.cmdresult([constants.IP_BIN, "link", "set", "dev",
self.ifname(ifindex), "address", str(addr)])
(status, result) = self.client.cmdresult([constants.IP_BIN, "link", "set", "dev",
self.ifname(ifindex), "address", str(addr)])
if status:
logger.error("error setting MAC address %s", str(addr))
@ -390,11 +318,11 @@ class SimpleLxcNode(PyCoreNode):
"""
if self.up:
if ":" in str(addr): # check if addr is ipv6
self.cmd([constants.IP_BIN, "addr", "add", str(addr),
"dev", self.ifname(ifindex)])
self.client.cmd([constants.IP_BIN, "addr", "add", str(addr),
"dev", self.ifname(ifindex)])
else:
self.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+",
"dev", self.ifname(ifindex)])
self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+",
"dev", self.ifname(ifindex)])
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
@ -411,7 +339,7 @@ class SimpleLxcNode(PyCoreNode):
logger.exception("trying to delete unknown address: %s" % addr)
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):
"""
@ -438,7 +366,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing
"""
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):
"""
@ -503,13 +431,12 @@ class SimpleLxcNode(PyCoreNode):
"type", "veth", "peer", "name", tmp2])
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())
subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)])
othernode.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname])
othernode.addnetif(PyCoreNetIf(othernode, otherifname),
othernode.newifindex())
othernode.client.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname])
othernode.addnetif(PyCoreNetIf(othernode, otherifname), othernode.newifindex())
def addfile(self, srcname, filename):
"""
@ -520,7 +447,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing
"""
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):
"""
@ -530,7 +457,7 @@ class SimpleLxcNode(PyCoreNode):
:param bool rescan: rescan flag
:return:
"""
return self.vnodeclient.getaddr(ifname=ifname, rescan=rescan)
return self.client.getaddr(ifname=ifname, rescan=rescan)
def netifstats(self, ifname=None):
"""
@ -539,7 +466,7 @@ class SimpleLxcNode(PyCoreNode):
:param str ifname: interface name to get state for
:return:
"""
return self.vnodeclient.netifstats(ifname=ifname)
return self.client.netifstats(ifname=ifname)
class LxcNode(SimpleLxcNode):

View file

@ -6,17 +6,12 @@ by invoking the vcmd shell command.
"""
import os
import stat
import subprocess
import vcmd
from core import constants
from core import logger
USE_VCMD_MODULE = True
if USE_VCMD_MODULE:
import vcmd
VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd")
@ -34,12 +29,19 @@ class VnodeClient(object):
"""
self.name = name
self.ctrlchnlname = ctrlchnlname
if USE_VCMD_MODULE:
self.cmdchnl = vcmd.VCmd(self.ctrlchnlname)
else:
self.cmdchnl = None
self.cmdchnl = vcmd.VCmd(self.ctrlchnlname)
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):
"""
Check if node is connected or not.
@ -47,10 +49,7 @@ class VnodeClient(object):
:return: True if connected, False otherwise
:rtype: bool
"""
if USE_VCMD_MODULE:
return self.cmdchnl.connected()
else:
return True
return self.cmdchnl.connected()
def close(self):
"""
@ -58,8 +57,7 @@ class VnodeClient(object):
:return: nothing
"""
if USE_VCMD_MODULE:
self.cmdchnl.close()
self.cmdchnl.close()
def cmd(self, args, wait=True):
"""
@ -70,24 +68,16 @@ class VnodeClient(object):
:return: command status
:rtype: int
"""
if USE_VCMD_MODULE:
if not self.cmdchnl.connected():
raise ValueError("self.cmdchnl not connected")
tmp = self.cmdchnl.qcmd(args)
if not wait:
return tmp
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
self._verify_connection()
# TODO: clean this up after checking return value for qcmd
tmp = self.cmdchnl.qcmd(args)
if not wait:
return tmp
tmp = tmp.wait()
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
@ -101,14 +91,16 @@ class VnodeClient(object):
:return: command status and combined stdout and stderr output
:rtype: tuple[int, str]
"""
cmdid, cmdin, cmdout, cmderr = self.popen(args)
result = cmdout.read()
result += cmderr.read()
cmdin.close()
cmdout.close()
cmderr.close()
status = cmdid.wait()
return status, result
self._verify_connection()
p, stdin, stdout, stderr = self.popen(args)
output = stdout.read() + stderr.read()
stdin.close()
stdout.close()
stderr.close()
status = p.wait()
return status, output
def popen(self, args):
"""
@ -118,15 +110,8 @@ class VnodeClient(object):
:return: popen object, stdin, stdout, and stderr
:rtype: tuple
"""
if USE_VCMD_MODULE:
if not self.cmdchnl.connected():
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
self._verify_connection()
return self.cmdchnl.popen(args)
def icmd(self, args):
"""
@ -151,18 +136,20 @@ class VnodeClient(object):
:return: command status
:rtype: int
"""
if not USE_VCMD_MODULE:
raise NotImplementedError
if not self.cmdchnl.connected():
raise ValueError("self.cmdchnl not connected")
self._verify_connection()
# TODO: clean this up after verifying redircmd return values
tmp = self.cmdchnl.redircmd(infd, outfd, errfd, args)
if not wait:
return tmp
tmp = tmp.wait()
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
# TODO: validate if this is ever used
def term(self, sh="/bin/sh"):
"""
Open a terminal on a node.
@ -171,8 +158,7 @@ class VnodeClient(object):
:return: terminal command result
:rtype: int
"""
cmd = ("xterm", "-ut", "-title", self.name, "-e",
VCMD, "-c", self.ctrlchnlname, "--", sh)
cmd = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh)
if "SUDO_USER" in os.environ:
cmd = ("su", "-s", "/bin/sh", "-c",
"exec " + " ".join(map(lambda x: "'%s'" % x, cmd)),
@ -210,35 +196,36 @@ class VnodeClient(object):
"""
if ifname in self._addr and not rescan:
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()
if line[0] == "link/ether":
tmp["ether"].append(line[1])
interface["ether"].append(line[1])
elif line[0] == "inet":
tmp["inet"].append(line[1])
interface["inet"].append(line[1])
elif line[0] == "inet6":
if line[3] == "global":
tmp["inet6"].append(line[1])
interface["inet6"].append(line[1])
elif line[3] == "link":
tmp["inet6link"].append(line[1])
interface["inet6link"].append(line[1])
else:
logger.warn("unknown scope: %s" % line[3])
err = cmderr.read()
cmdout.close()
cmderr.close()
status = cmdid.wait()
err = stderr.read()
stdout.close()
stderr.close()
status = p.wait()
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:
logger.warn("error output: %s" % err)
self._addr[ifname] = tmp
return tmp
logger.warn("error output: %s", err)
self._addr[ifname] = interface
return interface
def netifstats(self, ifname=None):
"""
@ -250,15 +237,15 @@ class VnodeClient(object):
"""
stats = {}
cmd = ["cat", "/proc/net/dev"]
cmdid, cmdin, cmdout, cmderr = self.popen(cmd)
cmdin.close()
p, stdin, stdout, stderr = self.popen(cmd)
stdin.close()
# ignore first line
cmdout.readline()
stdout.readline()
# second line has count names
tmp = cmdout.readline().strip().split("|")
tmp = stdout.readline().strip().split("|")
rxkeys = tmp[1].split()
txkeys = tmp[2].split()
for line in cmdout:
for line in stdout:
line = line.strip().split()
devname, tmp = line[0].split(":")
if tmp:
@ -271,53 +258,15 @@ class VnodeClient(object):
for count in txkeys:
stats[devname]["tx"][count] = int(line[field])
field += 1
err = cmderr.read()
cmdout.close()
cmderr.close()
status = cmdid.wait()
err = stderr.read()
stdout.close()
stderr.close()
status = p.wait()
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:
logger.warn("error output: %s" % err)
logger.warn("error output: %s", err)
if ifname is not None:
return stats[ifname]
else:
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):
try:
# NOTE: this wait=False can be problematic!
node.cmd(shlex.split(cmd), wait=False)
node.client.cmd(shlex.split(cmd), wait=False)
except:
logger.exception("error starting command %s", cmd)
@ -358,7 +358,7 @@ class CoreServices(ConfigurableManager):
for cmd in service._startup:
try:
# NOTE: this wait=False can be problematic!
node.cmd(shlex.split(cmd), wait=False)
node.client.cmd(shlex.split(cmd), wait=False)
except:
logger.exception("error starting command %s", cmd)
@ -417,7 +417,7 @@ class CoreServices(ConfigurableManager):
for cmd in validate_cmds:
logger.info("validating service %s using: %s", service._name, cmd)
try:
status, result = node.cmdresult(shlex.split(cmd))
status, result = node.client.cmdresult(shlex.split(cmd))
if status != 0:
raise ValueError("non-zero exit status")
except:
@ -453,7 +453,7 @@ class CoreServices(ConfigurableManager):
else:
for cmd in service._shutdown:
try:
tmp = node.cmd(shlex.split(cmd), wait=True)
tmp = node.client.cmd(shlex.split(cmd), wait=True)
status += "%s" % tmp
except:
logger.exception("error running stop command %s", cmd)
@ -766,7 +766,7 @@ class CoreServices(ConfigurableManager):
for cmd in cmds:
try:
# 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:
fail += "Start %s(%s)," % (s._name, cmd)
except:

View file

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

View file

@ -59,7 +59,7 @@ def test(options):
# launches terminal for the first node
# 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
time.sleep(EbtablesQueue.rate)

View file

@ -82,7 +82,7 @@ def main():
for i in xrange(1, num_local + 1):
node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i)
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)
n.append(node)

View file

@ -84,7 +84,7 @@ def main():
tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i,
objid=i)
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)
session.services.addservicestonode(tmp, "", services_str)
n.append(tmp)

View file

@ -159,7 +159,7 @@ def main():
try:
n = session.add_object(cls=nodes.LxcNode, name="n%d" % i)
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:
session.services.addservicestonode(n, "", options.services)
n.boot()

View file

@ -72,9 +72,9 @@ def main():
prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i)
right = session.add_object(cls=nodes.PtpNet)
tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)])
tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
tmp.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.icmp_echo_ignore_broadcasts=0"])
tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"])
tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"])
tmp.setposition(x=100 * i, y=150)
n.append(tmp)
left = right

View file

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

View file

@ -57,7 +57,7 @@ def main():
for i in xrange(1, options.numnodes + 1):
tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i)
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)
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.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
n.append(tmp)
n[0].cmd(["iperf", "-s", "-D"])
n[-1].icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))])
n[0].cmd(["killall", "-9", "iperf"])
n[0].client.cmd(["iperf", "-s", "-D"])
n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))])
n[0].client.cmd(["killall", "-9", "iperf"])
raw_input("press enter to exit")
session.shutdown()

View file

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

View file

@ -186,18 +186,18 @@ class Core(object):
def ping(self, from_name, to_name):
from_node = self.nodes[from_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):
from_node = self.nodes[from_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()
def iping(self, from_name, to_name):
from_node = self.nodes[from_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):
from_node = self.nodes[from_name]
@ -205,9 +205,9 @@ class Core(object):
to_ip = str(self.get_ip(to_name))
# run iperf server, run client, kill iperf server
vcmd, stdin, stdout, stderr = to_node.popen(["iperf", "-s", "-u", "-y", "C"])
from_node.cmd(["iperf", "-u", "-t", "5", "-c", to_ip])
to_node.cmd(["killall", "-9", "iperf"])
vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"])
from_node.client.cmd(["iperf", "-u", "-t", "5", "-c", to_ip])
to_node.client.cmd(["killall", "-9", "iperf"])
return stdout.read().strip()

View file

@ -3,13 +3,12 @@ Unit tests for testing basic CORE networks.
"""
import os
import stat
import threading
import time
import pytest
from xml.etree import ElementTree
import pytest
from mock import MagicMock
from conftest import EMANE_SERVICES
@ -18,6 +17,7 @@ from core.enumerations import MessageFlags
from core.mobility import BasicRangeModel
from core.netns import nodes
from core.netns import vnodeclient
from core.netns.vnodeclient import VnodeClient
from core.phys.pnodes import PhysicalNode
from core.service import ServiceManager
from core.xml import xmlsession
@ -29,6 +29,24 @@ _XML_VERSIONS = ["0.0", "1.0"]
_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:
def test_import_service(self, core):
"""
@ -145,7 +163,7 @@ class TestCore:
# get node client for testing
n1 = core.get_node("n1")
client = n1.vnodeclient
client = n1.client
# instantiate session
core.session.instantiate()
@ -178,7 +196,7 @@ class TestCore:
assert not client.shcmd(command[0])
# check module methods
assert vnodeclient.createclients(core.session.session_dir)
assert createclients(core.session.session_dir)
# check convenience methods for interface information
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"])
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()