initial changes to try and cleanup shell commands used within core
This commit is contained in:
parent
49a2f77f45
commit
6b8ee13f5d
22 changed files with 185 additions and 291 deletions
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue