initial effort to remove swallowing exceptions within internal code

This commit is contained in:
Blake J. Harnden 2018-03-02 13:39:44 -08:00
parent a3356127d2
commit 43554cbb62
10 changed files with 423 additions and 399 deletions

View file

@ -37,9 +37,9 @@ class Position(object):
"""
Returns True if the position has actually changed.
:param x: x position
:param y: y position
:param z: z position
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
@ -113,9 +113,9 @@ class PyCoreObj(object):
"""
Set the (x,y,z) position of the object.
:param x: x position
:param y: y position
:param z: z position
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
@ -460,6 +460,22 @@ class PyCoreNet(PyCoreObj):
"""
linktype = LinkTypes.WIRED.value
def startup(self):
"""
Each object implements its own startup method.
:return: nothing
"""
raise NotImplementedError
def shutdown(self):
"""
Each object implements its own shutdown method.
:return: nothing
"""
raise NotImplementedError
def __init__(self, session, objid, name, start=True):
"""
Create a PyCoreNet instance.
@ -597,7 +613,7 @@ class PyCoreNetIf(object):
"""
Creates a PyCoreNetIf instance.
:param core.netns.vnode.SimpleLxcNode node: node for interface
:param core.coreobj.PyCoreNode node: node for interface
:param str name: interface name
:param mtu: mtu value
"""

View file

@ -21,31 +21,30 @@ def emane_version():
"""
global VERSION
global VERSIONSTR
args = ("emane", "--version")
try:
status, result = utils.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("error checking emane version")
status = -1
result = ""
args = ["emane", "--version"]
VERSION = EMANEUNK
if status == 0:
if result.startswith("0.7.4"):
VERSION = EMANE074
elif result.startswith("0.8.1"):
VERSION = EMANE081
elif result.startswith("0.9.1"):
VERSION = EMANE091
elif result.startswith("0.9.2"):
VERSION = EMANE092
elif result.startswith("0.9.3"):
VERSION = EMANE093
elif result.startswith("1.0.1"):
VERSION = EMANE101
VERSIONSTR = result.strip()
try:
status, output = utils.check_cmd(args)
if status == 0:
if output.startswith("0.7.4"):
VERSION = EMANE074
elif output.startswith("0.8.1"):
VERSION = EMANE081
elif output.startswith("0.9.1"):
VERSION = EMANE091
elif output.startswith("0.9.2"):
VERSION = EMANE092
elif output.startswith("0.9.3"):
VERSION = EMANE093
elif output.startswith("1.0.1"):
VERSION = EMANE101
except subprocess.CalledProcessError:
logger.exception("error checking emane version")
output = ""
VERSIONSTR = output.strip()
# set version variables for the Emane class

View file

@ -925,7 +925,8 @@ class EmaneManager(ConfigurableManager):
logger.exception("error adding route for event data")
try:
args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)]
args = 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(args))
status, output = node.check_cmd(args)
logger.info("Emane.startdaemons2() return code %d" % status)
@ -1163,14 +1164,15 @@ class EmaneManager(ConfigurableManager):
Return True if an EMANE process associated with the given node
is running, False otherwise.
"""
status = -1
args = ["pkill", "-0", "-x", "emane"]
status = -1
try:
if emane.VERSION < emane.EMANE092:
status = utils.check_cmd(args)
utils.check_cmd(args)
else:
status, _ = node.check_cmd(args)
node.check_cmd(args)
status = 0
except subprocess.CalledProcessError:
logger.exception("error checking if emane is running")

View file

@ -199,7 +199,7 @@ def cmd_output(args):
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
status = p.wait()
return status, stdout
return status, stdout.strip()
except OSError:
raise subprocess.CalledProcessError(-1, args)
@ -222,9 +222,9 @@ def check_cmd(args, **kwargs):
p = subprocess.Popen(args, **kwargs)
stdout, _ = p.communicate()
status = p.wait()
if status:
if status != 0:
raise subprocess.CalledProcessError(status, args, stdout)
return status, stdout
return status, stdout.strip()
except OSError:
raise subprocess.CalledProcessError(-1, args)

View file

@ -68,6 +68,7 @@ class CtrlNet(LxBrNet):
Startup functionality for the control network.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
if self.detectoldbridge():
return
@ -79,26 +80,23 @@ class CtrlNet(LxBrNet):
else:
addr = self.prefix.max_addr()
msg = "Added control network bridge: %s %s" % (self.brname, self.prefix)
addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)]
logger.info("added control network bridge: %s %s", self.brname, self.prefix)
if self.assign_address:
addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)]
self.addrconfig(addrlist=addrlist)
msg += " address %s" % addr
logger.info(msg)
logger.info("address %s", addr)
if self.updown_script is not None:
logger.info("interface %s updown script (%s startup) called",
self.brname, self.updown_script)
if self.updown_script:
logger.info("interface %s updown script (%s startup) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "startup"])
if self.serverintf is not None:
try:
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf])
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
except subprocess.CalledProcessError:
logger.exception("error joining server interface %s to controlnet bridge %s",
self.serverintf, self.brname)
if self.serverintf:
# sets the interface as a port of the bridge
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf])
# bring interface up
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
def detectoldbridge(self):
"""
@ -120,10 +118,9 @@ class CtrlNet(LxBrNet):
if len(flds) == 3:
if flds[0] == "b" and flds[1] == self.objid:
logger.error(
"Error: An active control net bridge (%s) found. "
"error: An active control net bridge (%s) found. "
"An older session might still be running. "
"Stop all sessions and, if needed, delete %s to continue." %
(oldbr, oldbr)
"Stop all sessions and, if needed, delete %s to continue.", oldbr, oldbr
)
return True
return False
@ -137,20 +134,26 @@ class CtrlNet(LxBrNet):
if self.serverintf is not None:
try:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf])
except subprocess.CalledProcessError:
logger.exception("error deleting server interface %s to controlnet bridge %s",
self.serverintf, self.brname)
except subprocess.CalledProcessError as e:
logger.exception("error deleting server interface %s from bridge %s: %s",
self.serverintf, self.brname, e.output)
if self.updown_script is not None:
logger.info("interface %s updown script (%s shutdown) called" % (self.brname, self.updown_script))
utils.check_cmd([self.updown_script, self.brname, "shutdown"])
try:
logger.info("interface %s updown script (%s shutdown) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "shutdown"])
except subprocess.CalledProcessError as e:
logger.exception("error issuing shutdown script shutdown: %s", e.output)
LxBrNet.shutdown(self)
def all_link_data(self, flags):
"""
Do not include CtrlNet in link messages describing this session.
:return: nothing
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
return []
@ -172,29 +175,36 @@ class PtpNet(LxBrNet):
"""
Attach a network interface, but limit attachment to two interfaces.
:param core.coreobj.PyCoreNetIf netif: network interface
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
if len(self._netif) >= 2:
raise ValueError("Point-to-point links support at most 2 network interfaces")
LxBrNet.attach(self, netif)
def data(self, message_type):
def data(self, message_type, lat=None, lon=None, alt=None):
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
:return: nothing
:param message_type: purpose for the data object we are creating
:param float lat: latitude
:param float lon: longitude
:param float alt: altitude
:return: node data object
:rtype: core.data.NodeData
"""
pass
return None
def all_link_data(self, flags):
"""
Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
:return: all link data
:rtype: list[LinkData]
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = []
@ -318,8 +328,11 @@ class HubNode(LxBrNet):
:param int objid: node id
:param str name: node namee
:param bool start: start flag
:raises subprocess.CalledProcessError: when there is a command exception
"""
LxBrNet.__init__(self, session, objid, name, start)
# TODO: move to startup method
if start:
utils.check_cmd([constants.BRCTL_BIN, "setageing", self.brname, "0"])
@ -353,7 +366,7 @@ class WlanNode(LxBrNet):
"""
Attach a network interface.
:param core.coreobj.PyCoreNetIf netif: network interface
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
LxBrNet.attach(self, netif)
@ -364,7 +377,6 @@ class WlanNode(LxBrNet):
x, y, z = netif.node.position.get()
# invokes any netif.poshook
netif.setposition(x, y, z)
# self.model.setlinkparams()
def setmodel(self, model, config):
"""
@ -398,25 +410,28 @@ class WlanNode(LxBrNet):
logger.info("updating model %s" % model_name)
if self.model is None or self.model.name != model_name:
return
model = self.model
if model.config_type == RegisterTlvs.WIRELESS.value:
if not model.updateconfig(values):
return
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
(x, y, z) = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.setlinkparams()
def all_link_data(self, flags):
"""
Retrieve all link data.
:param flags: link flags
:return: all link data
:rtype: list[LinkData]
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = LxBrNet.all_link_data(self, flags)
@ -446,7 +461,6 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:return:
"""
PyCoreNode.__init__(self, session, objid, name, start=start)
# this initializes net, params, poshook
PyCoreNetIf.__init__(self, node=self, name=name, mtu=mtu)
self.up = False
self.lock = threading.RLock()
@ -456,6 +470,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
self.localname = name
self.old_up = False
self.old_addrs = []
if start:
self.startup()
@ -464,15 +479,12 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
Set the interface in the up state.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
# interface will also be marked up during net.attach()
self.savestate()
try:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
self.up = True
except subprocess.CalledProcessError:
logger.exception("failed to run command: %s link set %s up", constants.IP_BIN, self.localname)
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
self.up = True
def shutdown(self):
"""
@ -504,6 +516,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
"""
PyCoreNetIf.attachnet(self, net)
# TODO: issue in that both classes inherited from provide the same method with different signatures
def detachnet(self):
"""
Detach a network.
@ -523,7 +536,9 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:param str hwaddr: hardware address
:param int ifindex: interface index
:param str ifname: interface name
:return:
:return: interface index
:rtype: int
:raises ValueError: when an interface has already been created, one max
"""
with self.lock:
if ifindex is None:
@ -556,14 +571,12 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
if ifindex is None:
ifindex = 0
if ifindex not in self._netif:
raise ValueError, "ifindex %s does not exist" % ifindex
self._netif.pop(ifindex)
if ifindex == self.ifindex:
self.shutdown()
else:
raise ValueError, "ifindex %s does not exist" % ifindex
raise ValueError("ifindex %s does not exist" % ifindex)
def netif(self, ifindex, net=None):
"""
@ -606,9 +619,11 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:param str addr: address to add
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
PyCoreNetIf.addaddr(self, addr)
def deladdr(self, addr):
@ -617,9 +632,11 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:param str addr: address to delete
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name])
PyCoreNetIf.deladdr(self, addr)
def savestate(self):
@ -628,35 +645,34 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
interface for emulation purposes. TODO: save/restore the PROMISC flag
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
self.old_up = False
self.old_addrs = []
args = [constants.IP_BIN, "addr", "show", "dev", self.localname]
try:
_, output = utils.check_cmd(args)
for line in output.split("\n"):
items = line.split()
if len(items) < 2:
continue
_, output = utils.check_cmd(args)
for line in output.split("\n"):
items = line.split()
if len(items) < 2:
continue
if items[1] == "%s:" % self.localname:
flags = items[2][1:-1].split(",")
if "UP" in flags:
self.old_up = True
elif items[0] == "inet":
self.old_addrs.append((items[1], items[3]))
elif items[0] == "inet6":
if items[1][:4] == "fe80":
continue
self.old_addrs.append((items[1], None))
except subprocess.CalledProcessError:
logger.exception("error during save state")
if items[1] == "%s:" % self.localname:
flags = items[2][1:-1].split(",")
if "UP" in flags:
self.old_up = True
elif items[0] == "inet":
self.old_addrs.append((items[1], items[3]))
elif items[0] == "inet6":
if items[1][:4] == "fe80":
continue
self.old_addrs.append((items[1], None))
def restorestate(self):
"""
Restore the addresses and other interface state after using it.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
for addr in self.old_addrs:
if addr[1] is None:
@ -669,13 +685,58 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
def setposition(self, x=None, y=None, z=None):
"""
Use setposition() from both parent classes.
Uses setposition from both parent classes.
:return: nothing
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
PyCoreObj.setposition(self, x, y, z)
# invoke any poshook
result = PyCoreObj.setposition(self, x, y, z)
PyCoreNetIf.setposition(self, x, y, z)
return result
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: exist status and combined stdout and stderr
:rtype: tuple[int, str]
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
raise NotImplementedError
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
raise NotImplementedError
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
raise NotImplementedError
def termcmdstring(self, sh):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
raise NotImplementedError
class TunnelNode(GreTapBridge):

View file

@ -78,24 +78,23 @@ class OvsNet(PyCoreNet):
ebtables_queue.startupdateloop(self)
def startup(self):
try:
utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name])
except subprocess.CalledProcessError:
logger.exception("error adding bridge")
"""
try:
# turn off spanning tree protocol and forwarding delay
# TODO: appears stp and rstp are off by default, make sure this always holds true
# TODO: apears ovs only supports rstp forward delay and again it's off by default
utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "up"])
:return:
:raises subprocess.CalledProcessError: when there is a command exception
"""
utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name])
# create a new ebtables chain for this bridge
ebtables_commands(utils.check_cmd, [
[constants.EBTABLES_BIN, "-N", self.bridge_name, "-P", self.policy],
[constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name]
])
except subprocess.CalledProcessError:
logger.exception("Error setting bridge parameters")
# turn off spanning tree protocol and forwarding delay
# TODO: appears stp and rstp are off by default, make sure this always holds true
# TODO: apears ovs only supports rstp forward delay and again it's off by default
utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "up"])
# create a new ebtables chain for this bridge
ebtables_commands(utils.check_cmd, [
[constants.EBTABLES_BIN, "-N", self.bridge_name, "-P", self.policy],
[constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name]
])
self.up = True
@ -127,22 +126,14 @@ class OvsNet(PyCoreNet):
def attach(self, interface):
if self.up:
try:
utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"])
except subprocess.CalledProcessError:
logger.exception("error joining interface %s to bridge %s", interface.localname, self.bridge_name)
return
utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"])
PyCoreNet.attach(self, interface)
def detach(self, interface):
if self.up:
try:
utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname])
except subprocess.CalledProcessError:
logger.exception("error removing interface %s from bridge %s", interface.localname, self.bridge_name)
return
utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname])
PyCoreNet.detach(self, interface)
@ -345,10 +336,7 @@ class OvsNet(PyCoreNet):
return
for address in addresses:
try:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name])
except subprocess.CalledProcessError:
logger.exception("error adding IP address")
utils.check_cmd([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name])
class OvsCtrlNet(OvsNet):
@ -392,20 +380,16 @@ class OvsCtrlNet(OvsNet):
utils.check_cmd([self.updown_script, self.bridge_name, "startup"])
if self.serverintf:
try:
utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf])
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
except subprocess.CalledProcessError:
logger.exception("error joining server interface %s to controlnet bridge %s",
self.serverintf, self.bridge_name)
utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf])
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
def detectoldbridge(self):
"""
Occassionally, control net bridges from previously closed sessions are not cleaned up.
Occasionally, control net bridges from previously closed sessions are not cleaned up.
Check if there are old control net bridges and delete them
"""
status, output = utils.cmd_output([constants.OVS_BIN, "list-br"])
_, output = utils.check_cmd([constants.OVS_BIN, "list-br"])
output = output.strip()
if output:
for line in output.split("\n"):
@ -420,13 +404,16 @@ class OvsCtrlNet(OvsNet):
if self.serverintf:
try:
utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, self.serverintf])
except subprocess.CalledProcessError:
logger.exception("Error deleting server interface %s to controlnet bridge %s",
self.serverintf, self.bridge_name)
except subprocess.CalledProcessError as e:
logger.exception("error deleting server interface %s to controlnet bridge %s: %s",
self.serverintf, self.bridge_name, e.output)
if self.updown_script:
logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script)
utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"])
try:
logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script)
utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"])
except subprocess.CalledProcessError as e:
logger.exception("error during updown script shutdown: %s", e.output)
OvsNet.shutdown(self)
@ -445,12 +432,12 @@ class OvsPtpNet(OvsNet):
raise ValueError("point-to-point links support at most 2 network interfaces")
OvsNet.attach(self, interface)
def data(self, message_type):
def data(self, message_type, lat=None, lon=None, alt=None):
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
"""
pass
return None
def all_link_data(self, flags):
"""
@ -685,8 +672,8 @@ class OvsGreTapBridge(OvsNet):
if remoteip is None:
self.gretap = None
else:
self.gretap = GreTap(node=self, name=None, session=session, remoteip=remoteip,
objid=None, localip=localip, ttl=ttl, key=self.grekey)
self.gretap = GreTap(node=self, session=session, remoteip=remoteip,
localip=localip, ttl=ttl, key=self.grekey)
if start:
self.startup()
@ -726,7 +713,7 @@ class OvsGreTapBridge(OvsNet):
if len(addresses) > 1:
localip = addresses[1].split("/")[0]
self.gretap = GreTap(session=self.session, remoteip=remoteip, objid=None, name=None,
self.gretap = GreTap(session=self.session, remoteip=remoteip,
localip=localip, ttl=self.ttl, key=self.grekey)
self.attach(self.gretap)

View file

@ -31,7 +31,7 @@ class VEth(PyCoreNetIf):
:param mtu: interface mtu
:param net: network
:param bool start: start flag
:return:
:raises subprocess.CalledProcessError: when there is a command exception
"""
# note that net arg is ignored
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
@ -45,6 +45,7 @@ class VEth(PyCoreNetIf):
Interface startup logic.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
utils.check_cmd([constants.IP_BIN, "link", "add", "name", self.localname,
"type", "veth", "peer", "name", self.name])
@ -63,11 +64,14 @@ class VEth(PyCoreNetIf):
if self.node:
try:
self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name])
except subprocess.CalledProcessError:
logger.exception("error shutting down interface")
except subprocess.CalledProcessError as e:
logger.exception("error shutting down interface: %s", e.output)
if self.localname:
utils.mute_detach([constants.IP_BIN, "link", "delete", self.localname])
try:
utils.check_cmd([constants.IP_BIN, "link", "delete", self.localname])
except subprocess.CalledProcessError as e:
logger.exception("error deleting link: %s", e.output)
self.up = False
@ -121,8 +125,8 @@ class TunTap(PyCoreNetIf):
try:
self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name])
except subprocess.CalledProcessError:
logger.exception("error shutting down tunnel tap")
except subprocess.CalledProcessError as e:
logger.exception("error shutting down tunnel tap: %s", e.output)
self.up = False
@ -133,13 +137,16 @@ class TunTap(PyCoreNetIf):
:param func: function to wait for a result of zero
:param int attempts: number of attempts to wait for a zero result
:param float maxretrydelay: maximum retry delay
:return: nothing
:return: True if wait succeeded, False otherwise
:rtype: bool
"""
delay = 0.01
result = False
for i in xrange(1, attempts + 1):
r = func()
if r == 0:
return
result = True
break
msg = "attempt %s failed with nonzero exit status %s" % (i, r)
if i < attempts + 1:
msg += ", retrying..."
@ -152,7 +159,7 @@ class TunTap(PyCoreNetIf):
msg += ", giving up"
logger.info(msg)
raise RuntimeError("command failed after %s attempts" % attempts)
return result
def waitfordevicelocal(self):
"""
@ -182,18 +189,20 @@ class TunTap(PyCoreNetIf):
count = 0
while True:
try:
self.waitfor(nodedevexists)
result = self.waitfor(nodedevexists)
if result:
break
except RuntimeError as e:
# check if this is an EMANE interface; if so, continue
# waiting if EMANE is still running
# TODO: remove emane code
if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and self.node.session.emane.emanerunning(
self.node):
count += 1
else:
raise e
# check if this is an EMANE interface; if so, continue
# waiting if EMANE is still running
# TODO: remove emane code
should_retry = count < 5
is_emane_node = nodeutils.is_node(self.net, NodeTypes.EMANE)
is_emane_running = self.node.session.emane.emanerunning(self.node)
if all([should_retry, is_emane_node, is_emane_running]):
count += 1
else:
raise RuntimeError("node device failed to exist")
def install(self):
"""
@ -203,16 +212,13 @@ class TunTap(PyCoreNetIf):
end of the TAP.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
self.waitfordevicelocal()
netns = str(self.node.pid)
try:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "netns", netns])
self.node.check_cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name])
self.node.check_cmd([constants.IP_BIN, "link", "set", self.name, "up"])
except subprocess.CalledProcessError:
logger.exception("error installing TAP interface")
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "netns", netns])
self.node.check_cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name])
self.node.check_cmd([constants.IP_BIN, "link", "set", self.name, "up"])
def setaddrs(self):
"""
@ -222,10 +228,7 @@ class TunTap(PyCoreNetIf):
"""
self.waitfordevicenode()
for addr in self.addrlist:
try:
self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
except subprocess.CalledProcessError:
logger.exception("failure setting interface address")
self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
class GreTap(PyCoreNetIf):
@ -251,6 +254,7 @@ class GreTap(PyCoreNetIf):
:param ttl: ttl value
:param key: gre tap key
:param bool start: start flag
:raises subprocess.CalledProcessError: when there is a command exception
"""
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
self.session = session
@ -268,16 +272,16 @@ class GreTap(PyCoreNetIf):
if remoteip is None:
raise ValueError, "missing remote IP required for GRE TAP device"
args = ("ip", "link", "add", self.localname, "type", "gretap",
"remote", str(remoteip))
args = ["ip", "link", "add", self.localname, "type", "gretap",
"remote", str(remoteip)]
if localip:
args += ("local", str(localip))
args += ["local", str(localip)]
if ttl:
args += ("ttl", str(ttl))
args += ["ttl", str(ttl)]
if key:
args += ("key", str(key))
args += ["key", str(key)]
utils.check_cmd(args)
args = ("ip", "link", "set", self.localname, "up")
args = ["ip", "link", "set", self.localname, "up"]
utils.check_cmd(args)
self.up = True
@ -288,10 +292,14 @@ class GreTap(PyCoreNetIf):
:return: nothing
"""
if self.localname:
args = ("ip", "link", "set", self.localname, "down")
utils.check_cmd(args)
args = ("ip", "link", "del", self.localname)
utils.check_cmd(args)
try:
args = ["ip", "link", "set", self.localname, "down"]
utils.check_cmd(args)
args = ["ip", "link", "del", self.localname]
utils.check_cmd(args)
except subprocess.CalledProcessError as e:
logger.exception("error during shutdown: %s", e.output)
self.localname = None
def data(self, message_type):

View file

@ -59,11 +59,12 @@ class EbtablesQueue(object):
:return: nothing
"""
self.updatelock.acquire()
self.last_update_time[wlan] = time.time()
self.updatelock.release()
with self.updatelock:
self.last_update_time[wlan] = time.time()
if self.doupdateloop:
return
self.doupdateloop = True
self.updatethread = threading.Thread(target=self.updateloop)
self.updatethread.daemon = True
@ -75,15 +76,15 @@ class EbtablesQueue(object):
:return: nothing
"""
self.updatelock.acquire()
try:
del self.last_update_time[wlan]
except KeyError:
logger.exception("error deleting last update time for wlan, ignored before: %s", wlan)
with self.updatelock:
try:
del self.last_update_time[wlan]
except KeyError:
logger.exception("error deleting last update time for wlan, ignored before: %s", wlan)
self.updatelock.release()
if len(self.last_update_time) > 0:
return
self.doupdateloop = False
if self.updatethread:
self.updatethread.join()
@ -137,25 +138,26 @@ class EbtablesQueue(object):
:return: nothing
"""
while self.doupdateloop:
self.updatelock.acquire()
for wlan in self.updates:
"""
Check if wlan is from a previously closed session. Because of the
rate limiting scheme employed here, this may happen if a new session
is started soon after closing a previous session.
"""
try:
wlan.session
except:
# Just mark as updated to remove from self.updates.
self.updated(wlan)
continue
if self.lastupdate(wlan) > self.rate:
self.buildcmds(wlan)
# print "ebtables commit %d rules" % len(self.cmds)
self.ebcommit(wlan)
self.updated(wlan)
self.updatelock.release()
with self.updatelock:
for wlan in self.updates:
"""
Check if wlan is from a previously closed session. Because of the
rate limiting scheme employed here, this may happen if a new session
is started soon after closing a previous session.
"""
# TODO: if these are WlanNodes, this will never throw an exception
try:
wlan.session
except:
# Just mark as updated to remove from self.updates.
self.updated(wlan)
continue
if self.lastupdate(wlan) > self.rate:
self.buildcmds(wlan)
self.ebcommit(wlan)
self.updated(wlan)
time.sleep(self.rate)
def ebcommit(self, wlan):
@ -166,29 +168,22 @@ class EbtablesQueue(object):
"""
# save kernel ebtables snapshot to a file
args = self.ebatomiccmd(["--atomic-save", ])
try:
utils.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("atomic-save (%s)", args)
# no atomic file, exit
return
utils.check_cmd(args)
# modify the table file using queued ebtables commands
for c in self.cmds:
args = self.ebatomiccmd(c)
try:
utils.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("cmd=%s", args)
utils.check_cmd(args)
self.cmds = []
# commit the table file to the kernel
args = self.ebatomiccmd(["--atomic-commit", ])
utils.check_cmd(args)
try:
utils.check_cmd(args)
os.unlink(self.atomic_file)
except OSError:
logger.exception("atomic-commit (%s)", args)
logger.exception("error removing atomic file: %s", self.atomic_file)
def ebchange(self, wlan):
"""
@ -197,10 +192,9 @@ class EbtablesQueue(object):
:return: nothing
"""
self.updatelock.acquire()
if wlan not in self.updates:
self.updates.append(wlan)
self.updatelock.release()
with self.updatelock:
if wlan not in self.updates:
self.updates.append(wlan)
def buildcmds(self, wlan):
"""
@ -208,23 +202,22 @@ class EbtablesQueue(object):
:return: nothing
"""
wlan._linked_lock.acquire()
# flush the chain
self.cmds.extend([["-F", wlan.brname], ])
# rebuild the chain
for netif1, v in wlan._linked.items():
for netif2, linked in v.items():
if wlan.policy == "DROP" and linked:
self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname,
"-o", netif2.localname, "-j", "ACCEPT"],
["-A", wlan.brname, "-o", netif1.localname,
"-i", netif2.localname, "-j", "ACCEPT"]])
elif wlan.policy == "ACCEPT" and not linked:
self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname,
"-o", netif2.localname, "-j", "DROP"],
["-A", wlan.brname, "-o", netif1.localname,
"-i", netif2.localname, "-j", "DROP"]])
wlan._linked_lock.release()
with wlan._linked_lock:
# flush the chain
self.cmds.extend([["-F", wlan.brname], ])
# rebuild the chain
for netif1, v in wlan._linked.items():
for netif2, linked in v.items():
if wlan.policy == "DROP" and linked:
self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname,
"-o", netif2.localname, "-j", "ACCEPT"],
["-A", wlan.brname, "-o", netif1.localname,
"-i", netif2.localname, "-j", "ACCEPT"]])
elif wlan.policy == "ACCEPT" and not linked:
self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname,
"-o", netif2.localname, "-j", "DROP"],
["-A", wlan.brname, "-o", netif1.localname,
"-i", netif2.localname, "-j", "DROP"]])
# a global object because all WLANs share the same queue
@ -279,28 +272,24 @@ class LxBrNet(PyCoreNet):
Linux bridge starup logic.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
"""
try:
utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname])
except subprocess.CalledProcessError:
logger.exception("Error adding bridge")
utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname])
try:
# turn off spanning tree protocol and forwarding delay
utils.check_cmd([constants.BRCTL_BIN, "stp", self.brname, "off"])
utils.check_cmd([constants.BRCTL_BIN, "setfd", self.brname, "0"])
utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "up"])
# create a new ebtables chain for this bridge
ebtablescmds(utils.check_cmd, [
[constants.EBTABLES_BIN, "-N", self.brname, "-P", self.policy],
[constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.brname, "-j", self.brname]
])
# turn off multicast snooping so mcast forwarding occurs w/o IGMP joins
snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname
if os.path.exists(snoop):
open(snoop, "w").write("0")
except subprocess.CalledProcessError:
logger.exception("Error setting bridge parameters")
# turn off spanning tree protocol and forwarding delay
utils.check_cmd([constants.BRCTL_BIN, "stp", self.brname, "off"])
utils.check_cmd([constants.BRCTL_BIN, "setfd", self.brname, "0"])
utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "up"])
# create a new ebtables chain for this bridge
ebtablescmds(utils.check_cmd, [
[constants.EBTABLES_BIN, "-N", self.brname, "-P", self.policy],
[constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.brname, "-j", self.brname]
])
# turn off multicast snooping so mcast forwarding occurs w/o IGMP joins
snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname
if os.path.exists(snoop):
with open(snoop, "w") as snoop_file:
snoop_file.write("0")
self.up = True
@ -312,6 +301,7 @@ class LxBrNet(PyCoreNet):
"""
if not self.up:
return
ebq.stopupdateloop(self)
try:
@ -333,20 +323,18 @@ class LxBrNet(PyCoreNet):
del self.session
self.up = False
# TODO: this depends on a subtype with localname defined, seems like the wrong place for this to live
def attach(self, netif):
"""
Attach a network interface.
:param core.netns.vif.VEth netif: network interface to attach
:param core.netns.vnode.VEth netif: network interface to attach
:return: nothing
"""
if self.up:
try:
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"])
except subprocess.CalledProcessError:
logger.exception("Error joining interface %s to bridge %s", netif.localname, self.brname)
return
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"])
PyCoreNet.attach(self, netif)
def detach(self, netif):
@ -357,11 +345,8 @@ class LxBrNet(PyCoreNet):
:return: nothing
"""
if self.up:
try:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname])
except subprocess.CalledProcessError:
logger.exception("Error removing interface %s from bridge %s", netif.localname, self.brname)
return
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname])
PyCoreNet.detach(self, netif)
def linked(self, netif1, netif2):
@ -402,12 +387,11 @@ class LxBrNet(PyCoreNet):
:param core.netns.vif.Veth netif2: interface two
:return: nothing
"""
self._linked_lock.acquire()
if not self.linked(netif1, netif2):
self._linked_lock.release()
return
self._linked[netif1][netif2] = False
self._linked_lock.release()
with self._linked_lock:
if not self.linked(netif1, netif2):
return
self._linked[netif1][netif2] = False
ebq.ebchange(self)
def link(self, netif1, netif2):
@ -419,12 +403,11 @@ class LxBrNet(PyCoreNet):
:param core.netns.vif.Veth netif2: interface two
:return: nothing
"""
self._linked_lock.acquire()
if self.linked(netif1, netif2):
self._linked_lock.release()
return
self._linked[netif1][netif2] = True
self._linked_lock.release()
with self._linked_lock:
if self.linked(netif1, netif2):
return
self._linked[netif1][netif2] = True
ebq.ebchange(self)
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None,
@ -525,18 +508,21 @@ class LxBrNet(PyCoreNet):
self_objid = "%x" % self.objid
except TypeError:
self_objid = "%s" % self.objid
try:
net_objid = "%x" % net.objid
except TypeError:
net_objid = "%s" % net.objid
localname = "veth%s.%s.%s" % (self_objid, net_objid, sessionid)
if len(localname) >= 16:
raise ValueError("interface local name %s too long" % localname)
name = "veth%s.%s.%s" % (net_objid, self_objid, sessionid)
if len(name) >= 16:
raise ValueError("interface name %s too long" % name)
netif = VEth(node=None, name=name, localname=localname,
mtu=1500, net=self, start=self.up)
netif = VEth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up)
self.attach(netif)
if net.up:
# this is similar to net.attach() but uses netif.name instead
@ -563,6 +549,7 @@ class LxBrNet(PyCoreNet):
for netif in self.netifs():
if hasattr(netif, "othernet") and netif.othernet == net:
return netif
return None
def addrconfig(self, addrlist):
@ -574,11 +561,9 @@ class LxBrNet(PyCoreNet):
"""
if not self.up:
return
for addr in addrlist:
try:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname])
except subprocess.CalledProcessError:
logger.exception("Error adding IP address")
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname])
class GreTapBridge(LxBrNet):
@ -615,8 +600,8 @@ class GreTapBridge(LxBrNet):
if remoteip is None:
self.gretap = None
else:
self.gretap = GreTap(node=self, name=None, session=session, remoteip=remoteip,
objid=None, localip=localip, ttl=ttl, key=self.grekey)
self.gretap = GreTap(node=self, session=session, remoteip=remoteip,
localip=localip, ttl=ttl, key=self.grekey)
if start:
self.startup()
@ -658,7 +643,7 @@ class GreTapBridge(LxBrNet):
localip = None
if len(addrlist) > 1:
localip = addrlist[1].split("/")[0]
self.gretap = GreTap(session=self.session, remoteip=remoteip, objid=None, name=None,
self.gretap = GreTap(session=self.session, remoteip=remoteip,
localip=localip, ttl=self.ttl, key=self.grekey)
self.attach(self.gretap)

View file

@ -98,25 +98,19 @@ class SimpleLxcNode(PyCoreNode):
env["NODE_NUMBER"] = str(self.objid)
env["NODE_NAME"] = str(self.name)
try:
_, output = utils.check_cmd(vnoded, env=env)
self.pid = int(output)
except subprocess.CalledProcessError:
logger.exception("vnoded failed to create a namespace; check kernel support and user privileges")
_, output = utils.check_cmd(vnoded, env=env)
self.pid = int(output)
# create vnode client
self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname)
try:
# bring up the loopback interface
logger.info("bringing up loopback interface")
self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"])
# bring up the loopback interface
logger.info("bringing up loopback interface")
self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"])
# set hostname for node
logger.info("setting hostname: %s" % self.name)
self.check_cmd(["hostname", self.name])
except subprocess.CalledProcessError:
logger.exception("error setting up loopback and hostname: %s")
# set hostname for node
logger.info("setting hostname: %s" % self.name)
self.check_cmd(["hostname", self.name])
# mark node as up
self.up = True
@ -165,7 +159,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing
"""
pass
return None
def cmd(self, args, wait=True):
"""
@ -208,7 +202,6 @@ class SimpleLxcNode(PyCoreNode):
"""
return self.client.termcmdstring(sh)
# TODO: should change how this exception is just swallowed up
def mount(self, source, target):
"""
Create and mount a directory.
@ -216,17 +209,15 @@ class SimpleLxcNode(PyCoreNode):
:param str source: source directory to mount
:param str target: target directory to create
:return: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
source = os.path.abspath(source)
logger.info("mounting %s at %s" % (source, target))
try:
cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target)
status, output = self.client.shcmd_result(cmd)
if status:
raise IOError("error during mount: %s" % output)
self._mounts.append((source, target))
except IOError:
logger.exception("mounting failed for %s at %s", source, target)
cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target)
status, output = self.client.shcmd_result(cmd)
if status:
raise subprocess.CalledProcessError(status, cmd, output)
self._mounts.append((source, target))
def umount(self, target):
"""
@ -238,8 +229,8 @@ class SimpleLxcNode(PyCoreNode):
logger.info("unmounting: %s", target)
try:
self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target])
except subprocess.CalledProcessError:
logger.exception("error during unmount")
except subprocess.CalledProcessError as e:
logger.exception("error during unmount: %s", e.output)
def newifindex(self):
"""
@ -277,33 +268,29 @@ class SimpleLxcNode(PyCoreNode):
localname = "veth" + suffix
if len(localname) >= 16:
raise ValueError("interface local name (%s) too long" % localname)
name = localname + "p"
if len(name) >= 16:
raise ValueError("interface name (%s) too long" % name)
veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up)
if self.up:
try:
utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
except subprocess.CalledProcessError:
logger.exception("failure setting eth name")
utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
veth.name = ifname
if self.up:
# TODO: potentially find better way to query interface ID
# retrieve interface information
try:
_, output = self.check_cmd(["ip", "link", "show", veth.name])
logger.info("interface command output: %s", output)
output = output.split("\n")
veth.flow_id = int(output[0].strip().split(":")[0]) + 1
logger.info("interface flow index: %s - %s", veth.name, veth.flow_id)
veth.hwaddr = output[1].strip().split()[1]
logger.info("interface mac: %s - %s", veth.name, veth.hwaddr)
except subprocess.CalledProcessError:
logger.exception("failure getting flow id and mac address")
_, output = self.check_cmd(["ip", "link", "show", veth.name])
logger.info("interface command output: %s", output)
output = output.split("\n")
veth.flow_id = int(output[0].strip().split(":")[0]) + 1
logger.info("interface flow index: %s - %s", veth.name, veth.flow_id)
veth.hwaddr = output[1].strip().split()[1]
logger.info("interface mac: %s - %s", veth.name, veth.hwaddr)
try:
self.addnetif(veth, ifindex)
@ -351,15 +338,13 @@ class SimpleLxcNode(PyCoreNode):
:param int ifindex: index of interface to set hardware address for
:param core.misc.ipaddress.MacAddress addr: hardware address to set
:return: mothing
:return: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
self._netif[ifindex].sethwaddr(addr)
if self.up:
args = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)]
try:
self.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("error setting MAC address %s: %s", addr)
self.check_cmd(args)
def addaddr(self, ifindex, addr):
"""
@ -370,16 +355,13 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing
"""
if self.up:
try:
# check if addr is ipv6
if ":" in str(addr):
args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]
self.check_cmd(args)
else:
args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)]
self.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("failure adding interface address")
# check if addr is ipv6
if ":" in str(addr):
args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]
self.check_cmd(args)
else:
args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)]
self.check_cmd(args)
self._netif[ifindex].addaddr(addr)
@ -390,6 +372,7 @@ class SimpleLxcNode(PyCoreNode):
:param int ifindex: index of interface to delete address from
:param str addr: address to delete from interface
:return: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
try:
self._netif[ifindex].deladdr(addr)
@ -397,10 +380,7 @@ class SimpleLxcNode(PyCoreNode):
logger.exception("trying to delete unknown address: %s" % addr)
if self.up:
try:
self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
except subprocess.CalledProcessError:
logger.exception("failure deleting address")
self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
def delalladdr(self, ifindex, address_types=valid_address_types):
"""
@ -409,6 +389,7 @@ class SimpleLxcNode(PyCoreNode):
:param int ifindex: index of interface to delete address types from
:param tuple[str] address_types: address types to delete
:return: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
interface_name = self.ifname(ifindex)
addresses = self.client.getaddr(interface_name, rescan=True)
@ -430,10 +411,7 @@ class SimpleLxcNode(PyCoreNode):
:return: nothing
"""
if self.up:
try:
self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"])
except subprocess.CalledProcessError:
logger.exception("failure bringing interface up")
self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"])
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
"""
@ -510,17 +488,15 @@ class SimpleLxcNode(PyCoreNode):
:param str srcname: source file name
:param str filename: file name to add
:return: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
"""
logger.info("adding file from %s to %s", srcname, filename)
directory = os.path.dirname(filename)
try:
cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename)
status, output = self.client.shcmd_result(cmd)
if status:
raise IOError("error adding file: %s" % output)
except IOError:
logger.exception("error during addfile")
cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename)
status, output = self.client.shcmd_result(cmd)
if status:
raise subprocess.CalledProcessError(status, cmd, output)
class LxcNode(SimpleLxcNode):
@ -567,13 +543,10 @@ class LxcNode(SimpleLxcNode):
:return: nothing
"""
with self.lock:
try:
self.makenodedir()
super(LxcNode, self).startup()
self.privatedir("/var/run")
self.privatedir("/var/log")
except OSError:
logger.exception("error during startup")
self.makenodedir()
super(LxcNode, self).startup()
self.privatedir("/var/run")
self.privatedir("/var/log")
def shutdown(self):
"""
@ -585,8 +558,6 @@ class LxcNode(SimpleLxcNode):
return
with self.lock:
# services are instead stopped when session enters datacollect state
# self.session.services.stopnodeservices(self)
try:
super(LxcNode, self).shutdown()
except OSError:
@ -605,12 +576,7 @@ class LxcNode(SimpleLxcNode):
if path[0] != "/":
raise ValueError("path not fully qualified: %s" % path)
hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip("/").replace("/", "."))
try:
os.mkdir(hostpath)
except OSError:
logger.exception("error creating directory: %s", hostpath)
os.mkdir(hostpath)
self.mount(hostpath, path)
def hostfilename(self, filename):
@ -622,7 +588,7 @@ class LxcNode(SimpleLxcNode):
"""
dirname, basename = os.path.split(filename)
if not basename:
raise ValueError("no basename for filename: " + filename)
raise ValueError("no basename for filename: %s" % filename)
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")

View file

@ -109,7 +109,7 @@ class VnodeClient(object):
:raises subprocess.CalledProcessError: when there is a non-zero exit status
"""
status, output = self.cmd_output(args)
if status:
if status != 0:
raise subprocess.CalledProcessError(status, args, output)
return status, output.strip()
@ -174,8 +174,8 @@ class VnodeClient(object):
args = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh)
if "SUDO_USER" in os.environ:
args = ("su", "-s", "/bin/sh", "-c",
"exec " + " ".join(map(lambda x: "'%s'" % x, args)),
os.environ["SUDO_USER"])
"exec " + " ".join(map(lambda x: "'%s'" % x, args)),
os.environ["SUDO_USER"])
return os.spawnvp(os.P_NOWAIT, args[0], args)
def termcmdstring(self, sh="/bin/sh"):