further cleanup to vnode.py and corrections to function docs
This commit is contained in:
parent
01060c50ff
commit
719670c895
9 changed files with 133 additions and 162 deletions
|
@ -323,7 +323,7 @@ class PyCoreNode(PyCoreObj):
|
||||||
if ifindex in self._netif:
|
if ifindex in self._netif:
|
||||||
raise ValueError("ifindex %s already exists" % ifindex)
|
raise ValueError("ifindex %s already exists" % ifindex)
|
||||||
self._netif[ifindex] = netif
|
self._netif[ifindex] = netif
|
||||||
# TODO: this hould have probably been set ahead, seems bad to me, check for failure and fix
|
# TODO: this should have probably been set ahead, seems bad to me, check for failure and fix
|
||||||
netif.netindex = ifindex
|
netif.netindex = ifindex
|
||||||
|
|
||||||
def delnetif(self, ifindex):
|
def delnetif(self, ifindex):
|
||||||
|
|
|
@ -215,7 +215,7 @@ class EventLoop(object):
|
||||||
"""
|
"""
|
||||||
Add an event to the event loop.
|
Add an event to the event loop.
|
||||||
|
|
||||||
:param int delaysec: delay in seconds for event
|
:param float delaysec: delay in seconds for event
|
||||||
:param func: event function
|
:param func: event function
|
||||||
:param args: event arguments
|
:param args: event arguments
|
||||||
:param kwds: event keyword arguments
|
:param kwds: event keyword arguments
|
||||||
|
|
|
@ -25,7 +25,7 @@ class VEth(PyCoreNetIf):
|
||||||
"""
|
"""
|
||||||
Creates a VEth instance.
|
Creates a VEth instance.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: related core node
|
:param core.netns.vnode.SimpleLxcNode node: related core node
|
||||||
:param str name: interface name
|
:param str name: interface name
|
||||||
:param str localname: interface local name
|
:param str localname: interface local name
|
||||||
:param mtu: interface mtu
|
:param mtu: interface mtu
|
||||||
|
@ -76,7 +76,7 @@ class TunTap(PyCoreNetIf):
|
||||||
"""
|
"""
|
||||||
Create a TunTap instance.
|
Create a TunTap instance.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: related core node
|
:param core.netns.vnode.SimpleLxcNode node: related core node
|
||||||
:param str name: interface name
|
:param str name: interface name
|
||||||
:param str localname: local interface name
|
:param str localname: local interface name
|
||||||
:param mtu: interface mtu
|
:param mtu: interface mtu
|
||||||
|
@ -136,7 +136,7 @@ class TunTap(PyCoreNetIf):
|
||||||
msg += ", retrying..."
|
msg += ", retrying..."
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
delay = delay + delay
|
delay += delay
|
||||||
if delay > maxretrydelay:
|
if delay > maxretrydelay:
|
||||||
delay = maxretrydelay
|
delay = maxretrydelay
|
||||||
else:
|
else:
|
||||||
|
@ -168,7 +168,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.client.cmd(cmd)
|
return self.node.client.cmd(cmd)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -180,8 +180,8 @@ class TunTap(PyCoreNetIf):
|
||||||
# check if this is an EMANE interface; if so, continue
|
# check if this is an EMANE interface; if so, continue
|
||||||
# waiting if EMANE is still running
|
# waiting if EMANE is still running
|
||||||
# TODO: remove emane code
|
# TODO: remove emane code
|
||||||
if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and \
|
if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and self.node.session.emane.emanerunning(
|
||||||
self.node.session.emane.emanerunning(self.node):
|
self.node):
|
||||||
count += 1
|
count += 1
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
@ -233,7 +233,7 @@ class GreTap(PyCoreNetIf):
|
||||||
"""
|
"""
|
||||||
Creates a GreTap instance.
|
Creates a GreTap instance.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: related core node
|
:param core.netns.vnode.SimpleLxcNode node: related core node
|
||||||
:param str name: interface name
|
:param str name: interface name
|
||||||
:param core.session.Session session: core session instance
|
:param core.session.Session session: core session instance
|
||||||
:param mtu: interface mtu
|
:param mtu: interface mtu
|
||||||
|
|
|
@ -21,6 +21,8 @@ from core.netns import vnodeclient
|
||||||
from core.netns.vif import TunTap
|
from core.netns.vif import TunTap
|
||||||
from core.netns.vif import VEth
|
from core.netns.vif import VEth
|
||||||
|
|
||||||
|
_DEFAULT_MTU = 1500
|
||||||
|
|
||||||
utils.check_executables([constants.IP_BIN])
|
utils.check_executables([constants.IP_BIN])
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:type lock: threading.RLock
|
:type lock: threading.RLock
|
||||||
:type _mounts: list[tuple[str, str]]
|
:type _mounts: list[tuple[str, str]]
|
||||||
"""
|
"""
|
||||||
valid_deladdrtype = ("inet", "inet6", "inet6link")
|
valid_address_types = {"inet", "inet6", "inet6link"}
|
||||||
|
|
||||||
def __init__(self, session, objid=None, name=None, nodedir=None, start=True):
|
def __init__(self, session, objid=None, name=None, nodedir=None, start=True):
|
||||||
"""
|
"""
|
||||||
|
@ -80,10 +82,16 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if self.up:
|
if self.up:
|
||||||
raise Exception("already up")
|
raise ValueError("starting a node that is already up")
|
||||||
vnoded = ["%s/vnoded" % constants.CORE_BIN_DIR, "-v", "-c", self.ctrlchnlname,
|
|
||||||
"-l", self.ctrlchnlname + ".log",
|
# create a new namespace for this node using vnoded
|
||||||
"-p", self.ctrlchnlname + ".pid"]
|
vnoded = [
|
||||||
|
"%s/vnoded" % constants.CORE_BIN_DIR,
|
||||||
|
"-v",
|
||||||
|
"-c", self.ctrlchnlname,
|
||||||
|
"-l", self.ctrlchnlname + ".log",
|
||||||
|
"-p", self.ctrlchnlname + ".pid"
|
||||||
|
]
|
||||||
if self.nodedir:
|
if self.nodedir:
|
||||||
vnoded += ["-C", self.nodedir]
|
vnoded += ["-C", self.nodedir]
|
||||||
env = self.session.get_environment(state=False)
|
env = self.session.get_environment(state=False)
|
||||||
|
@ -91,28 +99,26 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
env["NODE_NAME"] = str(self.name)
|
env["NODE_NAME"] = str(self.name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tmp = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env)
|
p = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env)
|
||||||
except OSError:
|
stdout, _ = p.communicate()
|
||||||
msg = "error running vnoded command: %s" % vnoded
|
if p.returncode:
|
||||||
logger.exception("SimpleLxcNode.startup(): %s", msg)
|
raise IOError("vnoded command failed: %s" % vnoded)
|
||||||
raise Exception(msg)
|
self.pid = int(stdout)
|
||||||
|
except (OSError, ValueError):
|
||||||
try:
|
logger.exception("vnoded failed to create a namespace; check kernel support and user priveleges")
|
||||||
self.pid = int(tmp.stdout.read())
|
|
||||||
tmp.stdout.close()
|
|
||||||
except ValueError:
|
|
||||||
msg = "vnoded failed to create a namespace; "
|
|
||||||
msg += "check kernel support and user priveleges"
|
|
||||||
logger.exception("SimpleLxcNode.startup(): %s", msg)
|
|
||||||
|
|
||||||
if tmp.wait():
|
|
||||||
raise Exception("command failed: %s" % vnoded)
|
|
||||||
|
|
||||||
|
# create vnode client
|
||||||
self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname)
|
self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname)
|
||||||
|
|
||||||
|
# bring up the loopback interface
|
||||||
logger.info("bringing up loopback interface")
|
logger.info("bringing up loopback interface")
|
||||||
self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"])
|
self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"])
|
||||||
|
|
||||||
|
# set hostname for node
|
||||||
logger.info("setting hostname: %s" % self.name)
|
logger.info("setting hostname: %s" % self.name)
|
||||||
self.client.cmd(["hostname", self.name])
|
self.client.cmd(["hostname", self.name])
|
||||||
|
|
||||||
|
# mark node as up
|
||||||
self.up = True
|
self.up = True
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
|
@ -146,7 +152,7 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
if os.path.exists(self.ctrlchnlname):
|
if os.path.exists(self.ctrlchnlname):
|
||||||
os.unlink(self.ctrlchnlname)
|
os.unlink(self.ctrlchnlname)
|
||||||
except OSError:
|
except OSError:
|
||||||
logger.exception("error removing file")
|
logger.exception("error removing node directory")
|
||||||
|
|
||||||
# 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()
|
||||||
|
@ -190,9 +196,11 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
"""
|
"""
|
||||||
logger.info("unmounting: %s", target)
|
logger.info("unmounting: %s", target)
|
||||||
try:
|
try:
|
||||||
self.client.cmd([constants.UMOUNT_BIN, "-n", "-l", target])
|
status, output = self.client.cmdresult([constants.UMOUNT_BIN, "-n", "-l", target])
|
||||||
|
if status:
|
||||||
|
raise IOError("error unmounting %s: %s", target, output)
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.exception("unmounting failed for %s" % target)
|
logger.exception("error during unmount")
|
||||||
|
|
||||||
def newifindex(self):
|
def newifindex(self):
|
||||||
"""
|
"""
|
||||||
|
@ -213,8 +221,7 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:param net: network to associate interface with
|
:param net: network to associate interface with
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
with self.lock:
|
||||||
try:
|
|
||||||
if ifindex is None:
|
if ifindex is None:
|
||||||
ifindex = self.newifindex()
|
ifindex = self.newifindex()
|
||||||
|
|
||||||
|
@ -234,7 +241,7 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
name = localname + "p"
|
name = localname + "p"
|
||||||
if len(name) >= 16:
|
if len(name) >= 16:
|
||||||
raise ValueError("interface name (%s) too long" % name)
|
raise ValueError("interface name (%s) too long" % name)
|
||||||
veth = VEth(node=self, name=name, localname=localname, mtu=1500, net=net, start=self.up)
|
veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up)
|
||||||
|
|
||||||
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)])
|
||||||
|
@ -255,14 +262,12 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.addnetif(veth, ifindex)
|
self.addnetif(veth, ifindex)
|
||||||
except:
|
except ValueError as e:
|
||||||
veth.shutdown()
|
veth.shutdown()
|
||||||
del veth
|
del veth
|
||||||
raise
|
raise e
|
||||||
|
|
||||||
return ifindex
|
return ifindex
|
||||||
finally:
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
def newtuntap(self, ifindex=None, ifname=None, net=None):
|
def newtuntap(self, ifindex=None, ifname=None, net=None):
|
||||||
"""
|
"""
|
||||||
|
@ -274,8 +279,7 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:return: interface index
|
:return: interface index
|
||||||
:rtype: int
|
:rtype: int
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
with self.lock:
|
||||||
try:
|
|
||||||
if ifindex is None:
|
if ifindex is None:
|
||||||
ifindex = self.newifindex()
|
ifindex = self.newifindex()
|
||||||
if ifname is None:
|
if ifname is None:
|
||||||
|
@ -283,18 +287,14 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
sessionid = self.session.short_session_id()
|
sessionid = self.session.short_session_id()
|
||||||
localname = "tap%s.%s.%s" % (self.objid, ifindex, sessionid)
|
localname = "tap%s.%s.%s" % (self.objid, ifindex, sessionid)
|
||||||
name = ifname
|
name = ifname
|
||||||
ifclass = TunTap
|
tuntap = TunTap(node=self, name=name, localname=localname, net=net, start=self.up)
|
||||||
tuntap = ifclass(node=self, name=name, localname=localname,
|
|
||||||
mtu=1500, net=net, start=self.up)
|
|
||||||
try:
|
try:
|
||||||
self.addnetif(tuntap, ifindex)
|
self.addnetif(tuntap, ifindex)
|
||||||
except Exception as e:
|
except ValueError as e:
|
||||||
tuntap.shutdown()
|
tuntap.shutdown()
|
||||||
del tuntap
|
del tuntap
|
||||||
raise e
|
raise e
|
||||||
return ifindex
|
return ifindex
|
||||||
finally:
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
def sethwaddr(self, ifindex, addr):
|
def sethwaddr(self, ifindex, addr):
|
||||||
"""
|
"""
|
||||||
|
@ -306,10 +306,10 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
"""
|
"""
|
||||||
self._netif[ifindex].sethwaddr(addr)
|
self._netif[ifindex].sethwaddr(addr)
|
||||||
if self.up:
|
if self.up:
|
||||||
(status, result) = self.client.cmdresult([constants.IP_BIN, "link", "set", "dev",
|
cmd = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)]
|
||||||
self.ifname(ifindex), "address", str(addr)])
|
status, output = self.client.cmdresult(cmd)
|
||||||
if status:
|
if status:
|
||||||
logger.error("error setting MAC address %s", str(addr))
|
logger.error("error setting MAC address %s: %s", addr, output)
|
||||||
|
|
||||||
def addaddr(self, ifindex, addr):
|
def addaddr(self, ifindex, addr):
|
||||||
"""
|
"""
|
||||||
|
@ -320,12 +320,13 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if self.up:
|
if self.up:
|
||||||
if ":" in str(addr): # check if addr is ipv6
|
# check if addr is ipv6
|
||||||
self.client.cmd([constants.IP_BIN, "addr", "add", str(addr),
|
if ":" in str(addr):
|
||||||
"dev", self.ifname(ifindex)])
|
cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]
|
||||||
|
self.client.cmd(cmd)
|
||||||
else:
|
else:
|
||||||
self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+",
|
cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)]
|
||||||
"dev", self.ifname(ifindex)])
|
self.client.cmd(cmd)
|
||||||
self._netif[ifindex].addaddr(addr)
|
self._netif[ifindex].addaddr(addr)
|
||||||
|
|
||||||
def deladdr(self, ifindex, addr):
|
def deladdr(self, ifindex, addr):
|
||||||
|
@ -344,22 +345,23 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
if self.up:
|
if self.up:
|
||||||
self.client.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, address_types=valid_address_types):
|
||||||
"""
|
"""
|
||||||
Delete all addresses from an interface.
|
Delete all addresses from an interface.
|
||||||
|
|
||||||
:param int ifindex: index of interface to delete all addresses from
|
:param int ifindex: index of interface to delete address types from
|
||||||
:param tuple addrtypes: address types to delete
|
:param tuple[str] address_types: address types to delete
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
addr = self.getaddr(self.ifname(ifindex), rescan=True)
|
interface_name = self.ifname(ifindex)
|
||||||
for t in addrtypes:
|
addresses = self.client.getaddr(interface_name, rescan=True)
|
||||||
if t not in self.valid_deladdrtype:
|
for address_type in address_types:
|
||||||
raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype))
|
if address_type not in self.valid_address_types:
|
||||||
for a in addr[t]:
|
raise ValueError("addr type must be in: %s" % " ".join(self.valid_address_types))
|
||||||
self.deladdr(ifindex, a)
|
for address in addresses[address_type]:
|
||||||
|
self.deladdr(ifindex, address)
|
||||||
# update cached information
|
# update cached information
|
||||||
self.getaddr(self.ifname(ifindex), rescan=True)
|
self.client.getaddr(interface_name, rescan=True)
|
||||||
|
|
||||||
def ifup(self, ifindex):
|
def ifup(self, ifindex):
|
||||||
"""
|
"""
|
||||||
|
@ -371,20 +373,22 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
if self.up:
|
if self.up:
|
||||||
self.client.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, address_list=None, hwaddr=None, ifindex=None, ifname=None):
|
||||||
"""
|
"""
|
||||||
Create a new network interface.
|
Create a new network interface.
|
||||||
|
|
||||||
:param net: network to associate with
|
:param net: network to associate with
|
||||||
:param list addrlist: addresses to add on the interface
|
:param list address_list: addresses to add on the interface
|
||||||
:param core.misc.ipaddress.MacAddress hwaddr: hardware address to set for interface
|
:param core.misc.ipaddress.MacAddress hwaddr: hardware address to set for interface
|
||||||
:param int ifindex: index of interface to create
|
:param int ifindex: index of interface to create
|
||||||
:param str ifname: name for interface
|
:param str ifname: name for interface
|
||||||
:return: interface index
|
:return: interface index
|
||||||
:rtype: int
|
:rtype: int
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
if not address_list:
|
||||||
try:
|
address_list = []
|
||||||
|
|
||||||
|
with self.lock:
|
||||||
# TODO: see if you can move this to emane specific code
|
# TODO: see if you can move this to emane specific code
|
||||||
if nodeutils.is_node(net, NodeTypes.EMANE):
|
if nodeutils.is_node(net, NodeTypes.EMANE):
|
||||||
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
||||||
|
@ -395,8 +399,8 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
self.attachnet(ifindex, net)
|
self.attachnet(ifindex, net)
|
||||||
netif = self.netif(ifindex)
|
netif = self.netif(ifindex)
|
||||||
netif.sethwaddr(hwaddr)
|
netif.sethwaddr(hwaddr)
|
||||||
for addr in utils.maketuple(addrlist):
|
for address in utils.maketuple(address_list):
|
||||||
netif.addaddr(addr)
|
netif.addaddr(address)
|
||||||
return ifindex
|
return ifindex
|
||||||
else:
|
else:
|
||||||
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
|
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
|
||||||
|
@ -407,14 +411,11 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
if hwaddr:
|
if hwaddr:
|
||||||
self.sethwaddr(ifindex, hwaddr)
|
self.sethwaddr(ifindex, hwaddr)
|
||||||
|
|
||||||
if addrlist:
|
for address in utils.maketuple(address_list):
|
||||||
for addr in utils.maketuple(addrlist):
|
self.addaddr(ifindex, address)
|
||||||
self.addaddr(ifindex, addr)
|
|
||||||
|
|
||||||
self.ifup(ifindex)
|
self.ifup(ifindex)
|
||||||
return ifindex
|
return ifindex
|
||||||
finally:
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
def connectnode(self, ifname, othernode, otherifname):
|
def connectnode(self, ifname, othernode, otherifname):
|
||||||
"""
|
"""
|
||||||
|
@ -426,20 +427,19 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
tmplen = 8
|
tmplen = 8
|
||||||
tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase)
|
tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)])
|
||||||
for x in xrange(tmplen)])
|
tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)])
|
||||||
tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase)
|
subprocess.check_call([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2])
|
||||||
for x in xrange(tmplen)])
|
|
||||||
subprocess.check_call([constants.IP_BIN, "link", "add", "name", tmp1,
|
|
||||||
"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.client.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())
|
interface = PyCoreNetIf(node=self, name=ifname, mtu=_DEFAULT_MTU)
|
||||||
|
self.addnetif(interface, 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.client.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.newifindex())
|
other_interface = PyCoreNetIf(node=othernode, name=otherifname, mtu=_DEFAULT_MTU)
|
||||||
|
othernode.addnetif(other_interface, othernode.newifindex())
|
||||||
|
|
||||||
def addfile(self, srcname, filename):
|
def addfile(self, srcname, filename):
|
||||||
"""
|
"""
|
||||||
|
@ -456,29 +456,10 @@ class SimpleLxcNode(PyCoreNode):
|
||||||
cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename)
|
cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename)
|
||||||
status, output = self.client.shcmd_result(cmd)
|
status, output = self.client.shcmd_result(cmd)
|
||||||
if status:
|
if status:
|
||||||
logger.error("error adding file: %s", output)
|
raise IOError("error adding file: %s" % output)
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.exception("error during addfile")
|
logger.exception("error during addfile")
|
||||||
|
|
||||||
def getaddr(self, ifname, rescan=False):
|
|
||||||
"""
|
|
||||||
Wrapper around vnodeclient getaddr.
|
|
||||||
|
|
||||||
:param str ifname: interface name to get address for
|
|
||||||
:param bool rescan: rescan flag
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
return self.client.getaddr(ifname=ifname, rescan=rescan)
|
|
||||||
|
|
||||||
def netifstats(self, ifname=None):
|
|
||||||
"""
|
|
||||||
Wrapper around vnodeclient netifstate.
|
|
||||||
|
|
||||||
:param str ifname: interface name to get state for
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
return self.client.netifstats(ifname=ifname)
|
|
||||||
|
|
||||||
|
|
||||||
class LxcNode(SimpleLxcNode):
|
class LxcNode(SimpleLxcNode):
|
||||||
"""
|
"""
|
||||||
|
@ -523,16 +504,14 @@ class LxcNode(SimpleLxcNode):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
with self.lock:
|
||||||
try:
|
try:
|
||||||
self.makenodedir()
|
self.makenodedir()
|
||||||
super(LxcNode, self).startup()
|
super(LxcNode, self).startup()
|
||||||
self.privatedir("/var/run")
|
self.privatedir("/var/run")
|
||||||
self.privatedir("/var/log")
|
self.privatedir("/var/log")
|
||||||
except OSError:
|
except OSError:
|
||||||
logger.exception("error during LxcNode.startup()")
|
logger.exception("error during startup")
|
||||||
finally:
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
"""
|
"""
|
||||||
|
@ -542,16 +521,16 @@ class LxcNode(SimpleLxcNode):
|
||||||
"""
|
"""
|
||||||
if not self.up:
|
if not self.up:
|
||||||
return
|
return
|
||||||
self.lock.acquire()
|
|
||||||
# services are instead stopped when session enters datacollect state
|
with self.lock:
|
||||||
# self.session.services.stopnodeservices(self)
|
# services are instead stopped when session enters datacollect state
|
||||||
try:
|
# self.session.services.stopnodeservices(self)
|
||||||
super(LxcNode, self).shutdown()
|
try:
|
||||||
except:
|
super(LxcNode, self).shutdown()
|
||||||
logger.exception("error during shutdown")
|
except OSError:
|
||||||
finally:
|
logger.exception("error during shutdown")
|
||||||
self.rmnodedir()
|
finally:
|
||||||
self.lock.release()
|
self.rmnodedir()
|
||||||
|
|
||||||
# TODO: should change how this exception is just swallowed up
|
# TODO: should change how this exception is just swallowed up
|
||||||
def privatedir(self, path):
|
def privatedir(self, path):
|
||||||
|
@ -612,11 +591,10 @@ class LxcNode(SimpleLxcNode):
|
||||||
:param int mode: mode for file
|
:param int mode: mode for file
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
f = self.opennodefile(filename, "w")
|
with self.opennodefile(filename, "w") as open_file:
|
||||||
f.write(contents)
|
open_file.write(contents)
|
||||||
os.chmod(f.name, mode)
|
os.chmod(open_file.name, mode)
|
||||||
f.close()
|
logger.info("created nodefile: %s; mode: 0%o", open_file.name, mode)
|
||||||
logger.info("created nodefile: %s; mode: 0%o", f.name, mode)
|
|
||||||
|
|
||||||
def nodefilecopy(self, filename, srcfilename, mode=None):
|
def nodefilecopy(self, filename, srcfilename, mode=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -7,11 +7,7 @@ a list of available services to the GUI and for configuring individual
|
||||||
services.
|
services.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import importlib
|
|
||||||
import inspect
|
|
||||||
import os
|
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
|
|
||||||
|
@ -263,8 +259,8 @@ class CoreServices(ConfigurableManager):
|
||||||
"""
|
"""
|
||||||
Start all services on a node.
|
Start all services on a node.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to start services on
|
:param core.netns.vnode.LxcNode node: node to start services on
|
||||||
:return:
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
services = sorted(node.services, key=lambda service: service._startindex)
|
services = sorted(node.services, key=lambda service: service._startindex)
|
||||||
use_startup_service = any(map(self.is_startup_service, services))
|
use_startup_service = any(map(self.is_startup_service, services))
|
||||||
|
@ -285,7 +281,7 @@ class CoreServices(ConfigurableManager):
|
||||||
Start a service on a node. Create private dirs, generate config
|
Start a service on a node. Create private dirs, generate config
|
||||||
files, and execute startup commands.
|
files, and execute startup commands.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to boot services on
|
:param core.netns.vnode.LxcNode node: node to boot services on
|
||||||
:param CoreService service: service to start
|
:param CoreService service: service to start
|
||||||
:param list services: service list
|
:param list services: service list
|
||||||
:param bool use_startup_service: flag to use startup services or not
|
:param bool use_startup_service: flag to use startup services or not
|
||||||
|
@ -295,7 +291,7 @@ class CoreServices(ConfigurableManager):
|
||||||
self.bootnodecustomservice(node, service, services, use_startup_service)
|
self.bootnodecustomservice(node, service, services, use_startup_service)
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info("starting service %s (%s)" % (service._name, service._startindex))
|
logger.info("starting service %s (%s)", service._name, service._startindex)
|
||||||
for directory in service._dirs:
|
for directory in service._dirs:
|
||||||
try:
|
try:
|
||||||
node.privatedir(directory)
|
node.privatedir(directory)
|
||||||
|
@ -321,7 +317,7 @@ class CoreServices(ConfigurableManager):
|
||||||
Start a custom service on a node. Create private dirs, use supplied
|
Start a custom service on a node. Create private dirs, use supplied
|
||||||
config files, and execute supplied startup commands.
|
config files, and execute supplied startup commands.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to boot services on
|
:param core.netns.vnode.LxcNode node: node to boot services on
|
||||||
:param CoreService service: service to start
|
:param CoreService service: service to start
|
||||||
:param list services: service list
|
:param list services: service list
|
||||||
:param bool use_startup_service: flag to use startup services or not
|
:param bool use_startup_service: flag to use startup services or not
|
||||||
|
@ -368,7 +364,7 @@ class CoreServices(ConfigurableManager):
|
||||||
config references an existing file that should be copied.
|
config references an existing file that should be copied.
|
||||||
Returns True for local files, False for generated.
|
Returns True for local files, False for generated.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to copy service for
|
:param core.netns.vnode.LxcNode node: node to copy service for
|
||||||
:param str filename: file name for a configured service
|
:param str filename: file name for a configured service
|
||||||
:param str cfg: configuration string
|
:param str cfg: configuration string
|
||||||
:return: True if successful, False otherwise
|
:return: True if successful, False otherwise
|
||||||
|
@ -387,7 +383,7 @@ class CoreServices(ConfigurableManager):
|
||||||
"""
|
"""
|
||||||
Run validation commands for all services on a node.
|
Run validation commands for all services on a node.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to validate services for
|
:param core.netns.vnode.LxcNode node: node to validate services for
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
services = sorted(node.services, key=lambda service: service._startindex)
|
services = sorted(node.services, key=lambda service: service._startindex)
|
||||||
|
@ -398,7 +394,7 @@ class CoreServices(ConfigurableManager):
|
||||||
"""
|
"""
|
||||||
Run the validation command(s) for a service.
|
Run the validation command(s) for a service.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to validate service for
|
:param core.netns.vnode.LxcNode node: node to validate service for
|
||||||
:param CoreService service: service to validate
|
:param CoreService service: service to validate
|
||||||
:param list services: services for node
|
:param list services: services for node
|
||||||
:return: service validation status
|
:return: service validation status
|
||||||
|
@ -441,7 +437,7 @@ class CoreServices(ConfigurableManager):
|
||||||
"""
|
"""
|
||||||
Stop a service on a node.
|
Stop a service on a node.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to stop a service on
|
:param core.netns.vnode.LxcNode node: node to stop a service on
|
||||||
:param CoreService service: service to stop
|
:param CoreService service: service to stop
|
||||||
:return: status for stopping the services
|
:return: status for stopping the services
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
@ -647,7 +643,7 @@ class CoreServices(ConfigurableManager):
|
||||||
The file data is either auto-generated or comes from an existing config.
|
The file data is either auto-generated or comes from an existing config.
|
||||||
|
|
||||||
:param list services: service list
|
:param list services: service list
|
||||||
:param core.netns.nodes.CoreNode node: node to get service file from
|
:param core.netns.vnode.LxcNode node: node to get service file from
|
||||||
:param str filename: file name to retrieve
|
:param str filename: file name to retrieve
|
||||||
:return: file message for node
|
:return: file message for node
|
||||||
"""
|
"""
|
||||||
|
@ -887,7 +883,7 @@ class CoreService(object):
|
||||||
Return the configuration string to be written to a file or sent
|
Return the configuration string to be written to a file or sent
|
||||||
to the GUI for customization.
|
to the GUI for customization.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to generate config for
|
:param core.netns.vnode.LxcNode node: node to generate config for
|
||||||
:param str filename: file name to generate config for
|
:param str filename: file name to generate config for
|
||||||
:param list services: services for node
|
:param list services: services for node
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
@ -902,7 +898,7 @@ class CoreService(object):
|
||||||
overridden to provide node-specific commands that may be
|
overridden to provide node-specific commands that may be
|
||||||
based on other services.
|
based on other services.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to get startup for
|
:param core.netns.vnode.LxcNode node: node to get startup for
|
||||||
:param list services: services for node
|
:param list services: services for node
|
||||||
:return: startup commands
|
:return: startup commands
|
||||||
:rtype: tuple
|
:rtype: tuple
|
||||||
|
@ -917,7 +913,7 @@ class CoreService(object):
|
||||||
overriden to provide node-specific commands that may be
|
overriden to provide node-specific commands that may be
|
||||||
based on other services.
|
based on other services.
|
||||||
|
|
||||||
:param core.netns.nodes.CoreNode node: node to validate
|
:param core.netns.vnode.LxcNode node: node to validate
|
||||||
:param list services: services for node
|
:param list services: services for node
|
||||||
:return: validation commands
|
:return: validation commands
|
||||||
:rtype: tuple
|
:rtype: tuple
|
||||||
|
@ -939,10 +935,8 @@ class CoreService(object):
|
||||||
cls._shutdown, cls._validate, cls._meta, cls._starttime]
|
cls._shutdown, cls._validate, cls._meta, cls._starttime]
|
||||||
if not cls._custom:
|
if not cls._custom:
|
||||||
# this is always reached due to classmethod
|
# this is always reached due to classmethod
|
||||||
valmap[valmap.index(cls._configs)] = \
|
valmap[valmap.index(cls._configs)] = cls.getconfigfilenames(node.objid, services)
|
||||||
cls.getconfigfilenames(node.objid, services)
|
valmap[valmap.index(cls._startup)] = cls.getstartup(node, services)
|
||||||
valmap[valmap.index(cls._startup)] = \
|
|
||||||
cls.getstartup(node, services)
|
|
||||||
vals = map(lambda a, b: "%s=%s" % (a, str(b)), cls.keys, valmap)
|
vals = map(lambda a, b: "%s=%s" % (a, str(b)), cls.keys, valmap)
|
||||||
return "|".join(vals)
|
return "|".join(vals)
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ from core.service import CoreServices
|
||||||
from core.xen.xenconfig import XenConfigManager
|
from core.xen.xenconfig import XenConfigManager
|
||||||
from core.xml.xmlsession import save_session_xml
|
from core.xml.xmlsession import save_session_xml
|
||||||
|
|
||||||
|
|
||||||
# set default node map
|
# set default node map
|
||||||
node_map = nodemaps.NODES
|
node_map = nodemaps.NODES
|
||||||
nodeutils.set_node_map(node_map)
|
nodeutils.set_node_map(node_map)
|
||||||
|
@ -523,7 +522,7 @@ class Session(object):
|
||||||
if os.path.isfile(environment_config_file):
|
if os.path.isfile(environment_config_file):
|
||||||
utils.readfileintodict(environment_config_file, env)
|
utils.readfileintodict(environment_config_file, env)
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.exception("error reading environment configuration file: %s", environment_config_file)
|
logger.warn("environment configuration file does not exist: %s", environment_config_file)
|
||||||
|
|
||||||
# attempt to read and add user environment file
|
# attempt to read and add user environment file
|
||||||
if self.user:
|
if self.user:
|
||||||
|
@ -610,7 +609,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
|
:rtype: core.netns.vnode.LxcNode
|
||||||
"""
|
"""
|
||||||
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)
|
||||||
|
@ -1167,7 +1166,7 @@ class Session(object):
|
||||||
interface1 = node.newnetif(net=control_net,
|
interface1 = node.newnetif(net=control_net,
|
||||||
ifindex=control_net.CTRLIF_IDX_BASE + net_index,
|
ifindex=control_net.CTRLIF_IDX_BASE + net_index,
|
||||||
ifname="ctrl%d" % net_index, hwaddr=MacAddress.random(),
|
ifname="ctrl%d" % net_index, hwaddr=MacAddress.random(),
|
||||||
addrlist=addrlist)
|
address_list=addrlist)
|
||||||
node.netif(interface1).control = True
|
node.netif(interface1).control = True
|
||||||
|
|
||||||
def update_control_interface_hosts(self, net_index=0, remove=False):
|
def update_control_interface_hosts(self, net_index=0, remove=False):
|
||||||
|
|
|
@ -162,7 +162,7 @@ class CoreDocumentParser0(object):
|
||||||
hwaddr = addrstr
|
hwaddr = addrstr
|
||||||
else:
|
else:
|
||||||
addrlist.append(addrstr)
|
addrlist.append(addrstr)
|
||||||
i = n.newnetif(net, addrlist=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name)
|
i = n.newnetif(net, address_list=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name)
|
||||||
for model in ifc.getElementsByTagName("model"):
|
for model in ifc.getElementsByTagName("model"):
|
||||||
self.parsemodel(model, n, n.objid)
|
self.parsemodel(model, n, n.objid)
|
||||||
key = (n.name, name)
|
key = (n.name, name)
|
||||||
|
|
|
@ -389,7 +389,7 @@ class CoreDocumentParser1(object):
|
||||||
hwaddr = MacAddress.from_string(mac[0])
|
hwaddr = MacAddress.from_string(mac[0])
|
||||||
else:
|
else:
|
||||||
hwaddr = None
|
hwaddr = None
|
||||||
ifindex = node.newnetif(network, addrlist=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name)
|
ifindex = node.newnetif(network, address_list=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name)
|
||||||
# TODO: 'hostname' addresses are unused
|
# TODO: 'hostname' addresses are unused
|
||||||
msg = 'node \'%s\' interface \'%s\' connected ' \
|
msg = 'node \'%s\' interface \'%s\' connected ' \
|
||||||
'to network \'%s\'' % (node.name, if_name, network.name)
|
'to network \'%s\'' % (node.name, if_name, network.name)
|
||||||
|
|
|
@ -51,21 +51,21 @@ class CoreNs3Node(CoreNode, ns.network.Node):
|
||||||
kwds['objid'] = objid
|
kwds['objid'] = objid
|
||||||
CoreNode.__init__(self, *args, **kwds)
|
CoreNode.__init__(self, *args, **kwds)
|
||||||
|
|
||||||
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
|
def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None):
|
||||||
"""
|
"""
|
||||||
Add a network interface. If we are attaching to a CoreNs3Net, this
|
Add a network interface. If we are attaching to a CoreNs3Net, this
|
||||||
will be a TunTap. Otherwise dispatch to CoreNode.newnetif().
|
will be a TunTap. Otherwise dispatch to CoreNode.newnetif().
|
||||||
"""
|
"""
|
||||||
if not addrlist:
|
if not address_list:
|
||||||
addrlist = []
|
address_list = []
|
||||||
|
|
||||||
if not isinstance(net, CoreNs3Net):
|
if not isinstance(net, CoreNs3Net):
|
||||||
return CoreNode.newnetif(self, net, addrlist, hwaddr, ifindex, ifname)
|
return CoreNode.newnetif(self, net, address_list, hwaddr, ifindex, ifname)
|
||||||
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
|
||||||
self.attachnet(ifindex, net)
|
self.attachnet(ifindex, net)
|
||||||
netif = self.netif(ifindex)
|
netif = self.netif(ifindex)
|
||||||
netif.sethwaddr(hwaddr)
|
netif.sethwaddr(hwaddr)
|
||||||
for addr in maketuple(addrlist):
|
for addr in maketuple(address_list):
|
||||||
netif.addaddr(addr)
|
netif.addaddr(addr)
|
||||||
|
|
||||||
addrstr = netif.addrlist[0]
|
addrstr = netif.addrlist[0]
|
||||||
|
|
Loading…
Add table
Reference in a new issue