defined custom core command error that defaults to printing command output as well

This commit is contained in:
Blake J. Harnden 2018-03-02 16:22:20 -08:00
parent 29a3496eda
commit 974559843a
15 changed files with 90 additions and 81 deletions

View file

@ -2,10 +2,10 @@ import json
import logging
import logging.config
import os
import subprocess
from core import constants
# setup logging
log_config_path = os.path.join(constants.CORE_CONF_DIR, "logging.conf")
with open(log_config_path, "r") as log_config_file:
@ -14,3 +14,11 @@ with open(log_config_path, "r") as log_config_file:
logger = logging.getLogger()
class CoreCommandError(subprocess.CalledProcessError):
"""
Used when encountering internal CORE command errors.
"""
def __str__(self):
return "Command(%s), Status(%s):\n%s" % (self.cmd, self.returncode, self.output)

View file

@ -419,7 +419,7 @@ class PyCoreNode(PyCoreObj):
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
:raises CoreCommandError: when a non-zero exit status occurs
"""
raise NotImplementedError

View file

@ -1,5 +1,4 @@
import subprocess
from core import CoreCommandError
from core import logger
from core.misc import utils
@ -39,7 +38,7 @@ def emane_version():
VERSION = EMANE093
elif output.startswith("1.0.1"):
VERSION = EMANE101
except subprocess.CalledProcessError:
except CoreCommandError:
logger.exception("error checking emane version")
output = ""

View file

@ -3,10 +3,10 @@ emane.py: definition of an Emane class for implementing configuration control of
"""
import os
import subprocess
import threading
from xml.dom.minidom import parseString
from core import CoreCommandError
from core import constants
from core import emane
from core import logger
@ -949,7 +949,7 @@ class EmaneManager(ConfigurableManager):
try:
utils.check_cmd(args)
utils.check_cmd(["killall", "-q", "emanetransportd"])
except subprocess.CalledProcessError:
except CoreCommandError:
logger.exception("error shutting down emane daemons")
def installnetifs(self, do_netns=True):

View file

@ -12,6 +12,7 @@ import sys
import fcntl
import resource
from core import CoreCommandError
from core import logger
DEVNULL = open(os.devnull, "wb")
@ -181,7 +182,7 @@ def cmd(args, wait=True):
return 0
return p.wait()
except OSError:
raise subprocess.CalledProcessError(-1, args)
raise CoreCommandError(-1, args)
def cmd_output(args):
@ -192,7 +193,7 @@ def cmd_output(args):
:param list[str]|str args: command arguments
:return: command status and stdout
:rtype: tuple[int, str]
:raises subprocess.CalledProcessError: when the file to execute is not found
:raises CoreCommandError: when the file to execute is not found
"""
args = split_args(args)
try:
@ -201,7 +202,7 @@ def cmd_output(args):
status = p.wait()
return status, stdout.strip()
except OSError:
raise subprocess.CalledProcessError(-1, args)
raise CoreCommandError(-1, args)
def check_cmd(args, **kwargs):
@ -213,7 +214,7 @@ def check_cmd(args, **kwargs):
:param dict kwargs: keyword arguments to pass to subprocess.Popen
:return: combined stdout and stderr
:rtype: str
:raises subprocess.CalledProcessError: when there is a non-zero exit status or the file to execute is not found
:raises CoreCommandError: when there is a non-zero exit status or the file to execute is not found
"""
kwargs["stdout"] = subprocess.PIPE
kwargs["stderr"] = subprocess.STDOUT
@ -223,10 +224,10 @@ def check_cmd(args, **kwargs):
stdout, _ = p.communicate()
status = p.wait()
if status != 0:
raise subprocess.CalledProcessError(status, args, stdout)
raise CoreCommandError(status, args, stdout)
return stdout.strip()
except OSError:
raise subprocess.CalledProcessError(-1, args)
raise CoreCommandError(-1, args)
def hex_dump(s, bytes_per_word=2, words_per_line=8):

View file

@ -4,11 +4,11 @@ implementing specific node types.
"""
import socket
import subprocess
import threading
from socket import AF_INET
from socket import AF_INET6
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNetIf
@ -68,7 +68,7 @@ class CtrlNet(LxBrNet):
Startup functionality for the control network.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
if self.detectoldbridge():
return
@ -134,16 +134,15 @@ class CtrlNet(LxBrNet):
if self.serverintf is not None:
try:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf])
except subprocess.CalledProcessError as e:
logger.exception("error deleting server interface %s from bridge %s: %s",
self.serverintf, self.brname, e.output)
except CoreCommandError:
logger.exception("error deleting server interface %s from bridge %s", self.serverintf, self.brname)
if self.updown_script is not None:
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)
except CoreCommandError:
logger.exception("error issuing shutdown script shutdown")
LxBrNet.shutdown(self)
@ -328,7 +327,7 @@ 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
:raises CoreCommandError: when there is a command exception
"""
LxBrNet.__init__(self, session, objid, name, start)
@ -479,7 +478,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
Set the interface in the up state.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
# interface will also be marked up during net.attach()
self.savestate()
@ -500,8 +499,8 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"])
utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname])
utils.check_cmd([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"])
except subprocess.CalledProcessError as e:
logger.exception("error shutting down: %s", e.output)
except CoreCommandError:
logger.exception("error shutting down")
self.up = False
self.restorestate()
@ -619,7 +618,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:param str addr: address to add
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
@ -632,7 +631,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
:param str addr: address to delete
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name])
@ -645,7 +644,7 @@ 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
:raises CoreCommandError: when there is a command exception
"""
self.old_up = False
self.old_addrs = []
@ -672,7 +671,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
Restore the addresses and other interface state after using it.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
for addr in self.old_addrs:
if addr[1] is None:
@ -704,7 +703,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf):
: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
:raises CoreCommandError: when a non-zero exit status occurs
"""
raise NotImplementedError

View file

@ -3,11 +3,11 @@ TODO: probably goes away, or implement the usage of "unshare", or docker formal.
"""
import socket
import subprocess
import threading
from socket import AF_INET
from socket import AF_INET6
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNet
@ -81,7 +81,7 @@ class OvsNet(PyCoreNet):
"""
:return:
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name])
@ -112,8 +112,8 @@ class OvsNet(PyCoreNet):
[constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name],
[constants.EBTABLES_BIN, "-X", self.bridge_name]
])
except subprocess.CalledProcessError as e:
logger.exception("error bringing bridge down and removing it: %s", e.output)
except CoreCommandError:
logger.exception("error bringing bridge down and removing it")
# removes veth pairs used for bridge-to-bridge connections
for interface in self.netifs():
@ -404,16 +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 as e:
logger.exception("error deleting server interface %s to controlnet bridge %s: %s",
self.serverintf, self.bridge_name, e.output)
except CoreCommandError:
logger.exception("error deleting server interface %s to controlnet bridge %s",
self.serverintf, self.bridge_name)
if self.updown_script:
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)
except CoreCommandError:
logger.exception("error during updown script shutdown")
OvsNet.shutdown(self)

View file

@ -2,9 +2,9 @@
virtual ethernet classes that implement the interfaces available under Linux.
"""
import subprocess
import time
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNetIf
@ -31,7 +31,7 @@ class VEth(PyCoreNetIf):
:param mtu: interface mtu
:param net: network
:param bool start: start flag
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
# note that net arg is ignored
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
@ -45,7 +45,7 @@ class VEth(PyCoreNetIf):
Interface startup logic.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
utils.check_cmd([constants.IP_BIN, "link", "add", "name", self.localname,
"type", "veth", "peer", "name", self.name])
@ -64,14 +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 as e:
logger.exception("error shutting down interface: %s", e.output)
except CoreCommandError:
logger.exception("error shutting down interface")
if 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)
except CoreCommandError:
logger.exception("error deleting link")
self.up = False
@ -125,8 +125,8 @@ class TunTap(PyCoreNetIf):
try:
self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name])
except subprocess.CalledProcessError as e:
logger.exception("error shutting down tunnel tap: %s", e.output)
except CoreCommandError:
logger.exception("error shutting down tunnel tap")
self.up = False
@ -212,7 +212,7 @@ class TunTap(PyCoreNetIf):
end of the TAP.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
self.waitfordevicelocal()
netns = str(self.node.pid)
@ -254,7 +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
:raises CoreCommandError: when there is a command exception
"""
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
self.session = session
@ -297,8 +297,8 @@ class GreTap(PyCoreNetIf):
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)
except CoreCommandError:
logger.exception("error during shutdown")
self.localname = None

View file

@ -4,10 +4,10 @@ Linux Ethernet bridging and ebtables rules.
"""
import os
import subprocess
import threading
import time
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNet
@ -272,7 +272,7 @@ class LxBrNet(PyCoreNet):
Linux bridge starup logic.
:return: nothing
:raises subprocess.CalledProcessError: when there is a command exception
:raises CoreCommandError: when there is a command exception
"""
utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname])
@ -311,8 +311,8 @@ class LxBrNet(PyCoreNet):
[constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.brname, "-j", self.brname],
[constants.EBTABLES_BIN, "-X", self.brname]
])
except subprocess.CalledProcessError as e:
logger.exception("error during shutdown: %s", e.output)
except CoreCommandError:
logger.exception("error during shutdown")
# removes veth pairs used for bridge-to-bridge connections
for netif in self.netifs():

View file

@ -7,9 +7,9 @@ import random
import shutil
import signal
import string
import subprocess
import threading
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNetIf
@ -189,7 +189,7 @@ class SimpleLxcNode(PyCoreNode):
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
:raises CoreCommandError: when a non-zero exit status occurs
"""
return self.client.check_cmd(args)
@ -209,14 +209,14 @@ 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
:raises CoreCommandError: when a non-zero exit status occurs
"""
source = os.path.abspath(source)
logger.info("mounting %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)
raise CoreCommandError(status, cmd, output)
self._mounts.append((source, target))
def umount(self, target):
@ -229,8 +229,8 @@ class SimpleLxcNode(PyCoreNode):
logger.info("unmounting: %s", target)
try:
self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target])
except subprocess.CalledProcessError as e:
logger.exception("error during unmount: %s", e.output)
except CoreCommandError:
logger.exception("error during unmount")
def newifindex(self):
"""
@ -339,7 +339,7 @@ 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: nothing
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
:raises CoreCommandError: when a non-zero exit status occurs
"""
self._netif[ifindex].sethwaddr(addr)
if self.up:
@ -372,7 +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
:raises CoreCommandError: when a non-zero exit status occurs
"""
try:
self._netif[ifindex].deladdr(addr)
@ -389,7 +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
:raises CoreCommandError: when a non-zero exit status occurs
"""
interface_name = self.ifname(ifindex)
addresses = self.client.getaddr(interface_name, rescan=True)
@ -488,7 +488,7 @@ 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
:raises CoreCommandError: when a non-zero exit status occurs
"""
logger.info("adding file from %s to %s", srcname, filename)
directory = os.path.dirname(filename)
@ -496,7 +496,7 @@ class SimpleLxcNode(PyCoreNode):
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)
raise CoreCommandError(status, cmd, output)
class LxcNode(SimpleLxcNode):

View file

@ -6,10 +6,10 @@ by invoking the vcmd shell command.
"""
import os
import subprocess
import vcmd
from core import CoreCommandError
from core import constants
from core import logger
from core.misc import utils
@ -106,11 +106,11 @@ class VnodeClient(object):
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises subprocess.CalledProcessError: when there is a non-zero exit status
:raises core.CoreCommandError: when there is a non-zero exit status
"""
status, output = self.cmd_output(args)
if status != 0:
raise subprocess.CalledProcessError(status, args, output)
raise CoreCommandError(status, args, output)
return output.strip()
def popen(self, args):

View file

@ -6,6 +6,7 @@ import os
import subprocess
import threading
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNode
@ -91,11 +92,11 @@ class PhysicalNode(PyCoreNode):
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises subprocess.CalledProcessError: when a non-zero exit status occurs
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.cmd_output(args)
if status:
raise subprocess.CalledProcessError(status, args, output)
raise CoreCommandError(status, args, output)
return output.strip()
def shcmd(self, cmdstr, sh="/bin/sh"):
@ -224,8 +225,8 @@ class PhysicalNode(PyCoreNode):
logger.info("unmounting '%s'" % target)
try:
self.check_cmd([constants.UMOUNT_BIN, "-l", target])
except subprocess.CalledProcessError as e:
logger.exception("unmounting failed for %s: %s", target, e.output)
except CoreCommandError:
logger.exception("unmounting failed for %s", target)
def opennodefile(self, filename, mode="w"):
dirname, basename = os.path.split(filename)

View file

@ -6,10 +6,10 @@ The CoreServices class handles configuration messages for sending
a list of available services to the GUI and for configuring individual
services.
"""
import subprocess
import time
from itertools import repeat
from core import CoreCommandError
from core import logger
from core.conf import Configurable
from core.conf import ConfigurableManager
@ -413,7 +413,7 @@ class CoreServices(ConfigurableManager):
logger.info("validating service %s using: %s", service._name, args)
try:
node.check_cmd(args)
except subprocess.CalledProcessError:
except CoreCommandError:
logger.exception("validate command failed")
status = -1
@ -444,7 +444,7 @@ class CoreServices(ConfigurableManager):
for args in service._shutdown:
try:
node.check_cmd(args)
except subprocess.CalledProcessError:
except CoreCommandError:
logger.exception("error running stop command %s", args)
# TODO: determine if its ok to just return the bad exit status
status = "-1"
@ -756,8 +756,8 @@ class CoreServices(ConfigurableManager):
for args in cmds:
try:
node.check_cmd(args)
except subprocess.CalledProcessError:
logger.exception("error starting command %s", args)
except CoreCommandError:
logger.exception("error starting command")
fail += "Start %s(%s)," % (s._name, args)
if event_type == EventTypes.PAUSE.value:
status = self.validatenodeservice(node, s, services)

View file

@ -3,8 +3,8 @@ utility.py: defines miscellaneous utility services.
"""
import os
import subprocess
from core import CoreCommandError
from core import constants
from core.misc import utils
from core.misc.ipaddress import Ipv4Prefix
@ -419,7 +419,7 @@ class HttpService(UtilService):
"""
try:
status, result = utils.cmd_output(['a2query', '-v'])
except subprocess.CalledProcessError:
except CoreCommandError:
status = -1
if status == 0 and result[:3] == '2.4':

View file

@ -13,6 +13,7 @@ import threading
import crypt
from core import CoreCommandError
from core import constants
from core import logger
from core.coreobj import PyCoreNetIf
@ -263,7 +264,7 @@ class XenNode(PyCoreNode):
if self.booted:
utils.check_cmd([XM_PATH, "destroy", self.vmname])
self.booted = False
except (OSError, subprocess.CalledProcessError):
except CoreCommandError:
# ignore this error too, the VM may have exited already
logger.exception("error during shutdown")