removing cmd_output function from utils and nodes

This commit is contained in:
Blake Harnden 2019-10-11 09:34:49 -07:00
parent c3d27eb8a5
commit 4a6d69bb09
10 changed files with 51 additions and 193 deletions

View file

@ -10,6 +10,7 @@ from queue import Empty, Queue
import grpc
from core import utils
from core.api.grpc import core_pb2, core_pb2_grpc
from core.emane.nodes import EmaneNet
from core.emulator.data import (
@ -22,7 +23,7 @@ from core.emulator.data import (
)
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, LinkTypes, NodeTypes
from core.errors import CoreError
from core.errors import CoreCommandError, CoreError
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes.base import CoreNetworkBase
from core.nodes.docker import DockerNode
@ -882,7 +883,11 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("sending node command: %s", request)
session = self.get_session(request.session_id, context)
node = self.get_node(session, request.node_id, context)
_, output = node.cmd_output(request.command)
try:
args = utils.split_args(request.command)
output = node.node_net_cmd(args)
except CoreCommandError as e:
output = e.stderr
return core_pb2.NodeCommandResponse(output=output)
def GetNodeTerminal(self, request, context):

View file

@ -889,7 +889,12 @@ class CoreHandler(socketserver.BaseRequestHandler):
or message.flags & MessageFlags.TEXT.value
):
if message.flags & MessageFlags.LOCAL.value:
status, res = utils.cmd_output(command)
try:
res = utils.check_cmd(command)
status = 0
except CoreCommandError as e:
res = e.stderr
status = e.returncode
else:
try:
res = node.node_net_cmd(command)

View file

@ -421,16 +421,6 @@ class CoreNodeBase(NodeBase):
"""
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.
@ -598,16 +588,6 @@ class CoreNode(CoreNodeBase):
finally:
self.rmnodedir()
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]
"""
return self.client.cmd_output(args)
def node_net_cmd(self, args, wait=True):
"""
Runs a command that is used to configure and setup the network within a

View file

@ -57,46 +57,6 @@ class VnodeClient(object):
def _cmd_args(self):
return [constants.VCMD_BIN, "-c", self.ctrlchnlname, "--"]
def cmd(self, args, wait=True):
"""
Execute a command on a node and return the status (return code).
:param list[str]|str args: command arguments
:param bool wait: wait for command to end or not
:return: command status
:rtype: int
"""
self._verify_connection()
args = utils.split_args(args)
# run command, return process when not waiting
cmd = self._cmd_args() + args
logging.debug("cmd wait(%s): %s", wait, cmd)
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
if not wait:
return 0
# wait for and return exit status
return p.wait()
def cmd_output(self, args):
"""
Execute a command on a node and return a tuple containing the
exit status and result string. stderr output
is folded into the stdout result string.
:param list[str]|str args: command to run
:return: command status and combined stdout and stderr output
:rtype: tuple[int, str]
"""
p, stdin, stdout, stderr = self.popen(args)
stdin.close()
output = stdout.read() + stderr.read()
stdout.close()
stderr.close()
status = p.wait()
return status, output.decode("utf-8").strip()
def check_cmd(self, args, wait=True):
"""
Run command and return exit status and combined stdout and stderr.
@ -107,10 +67,16 @@ class VnodeClient(object):
:rtype: str
:raises core.CoreCommandError: when there is a non-zero exit status
"""
status, output = self.cmd_output(args)
p, stdin, stdout, stderr = self.popen(args)
stdin.close()
output = stdout.read() + stderr.read()
output = output.decode("utf-8").strip()
stdout.close()
stderr.close()
status = p.wait()
if wait and status != 0:
raise CoreCommandError(status, args, output)
return output.strip()
return output
def popen(self, args):
"""

View file

@ -27,12 +27,12 @@ class DockerClient(object):
def get_info(self):
args = "docker inspect {name}".format(name=self.name)
status, output = utils.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
output = utils.check_cmd(args)
data = json.loads(output)
if not data:
raise CoreCommandError(status, args, "docker({name}) not present".format(name=self.name))
raise CoreCommandError(
-1, args, "docker({name}) not present".format(name=self.name)
)
return data[0]
def is_alive(self):
@ -47,11 +47,11 @@ class DockerClient(object):
name=self.name
))
def cmd_output(self, cmd):
def check_cmd(self, cmd):
if isinstance(cmd, list):
cmd = " ".join(cmd)
logging.info("docker cmd output: %s", cmd)
return utils.cmd_output("docker exec {name} {cmd}".format(
return utils.check_cmd("docker exec {name} {cmd}".format(
name=self.name,
cmd=cmd
))
@ -64,13 +64,11 @@ class DockerClient(object):
cmd=cmd
)
logging.info("ns cmd: %s", args)
return utils.cmd_output(args)
return utils.check_cmd(args)
def get_pid(self):
args = "docker inspect -f '{{{{.State.Pid}}}}' {name}".format(name=self.name)
status, output = utils.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
output = utils.check_cmd(args)
self.pid = output
logging.debug("node(%s) pid: %s", self.name, self.pid)
return output
@ -81,9 +79,7 @@ class DockerClient(object):
name=self.name,
destination=destination
)
status, output = utils.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return utils.check_cmd(args)
class DockerNode(CoreNode):
@ -146,16 +142,6 @@ class DockerNode(CoreNode):
self.client.stop_container()
self.up = False
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]
"""
return self.client.cmd_output(args)
def check_cmd(self, args):
"""
Runs shell command on node.
@ -165,20 +151,14 @@ class DockerNode(CoreNode):
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.client.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return output
return self.client.check_cmd(args)
def node_net_cmd(self, args):
def node_net_cmd(self, args, wait=True):
if not self.up:
logging.debug("node down, not running network command: %s", args)
return 0
return ""
status, output = self.client.ns_cmd(args)
if status:
raise CoreCommandError(status, args, output)
return output
return self.client.ns_cmd(args)
def termcmdstring(self, sh="/bin/sh"):
"""

View file

@ -25,13 +25,11 @@ class LxdClient(object):
def get_info(self):
args = "lxc list {name} --format json".format(name=self.name)
status, output = utils.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
output = utils.check_cmd(args)
data = json.loads(output)
if not data:
raise CoreCommandError(
status, args, "LXC({name}) not present".format(name=self.name)
-1, args, "LXC({name}) not present".format(name=self.name)
)
return data[0]
@ -48,22 +46,22 @@ class LxdClient(object):
def _cmd_args(self, cmd):
return "lxc exec -nT {name} -- {cmd}".format(name=self.name, cmd=cmd)
def cmd_output(self, cmd):
def check_cmd(self, cmd):
if isinstance(cmd, list):
cmd = " ".join(cmd)
args = self._cmd_args(cmd)
logging.info("lxc cmd output: %s", args)
return utils.cmd_output(args)
return utils.check_cmd(args)
def _ns_args(self, cmd):
return "nsenter -t {pid} -m -u -i -p -n {cmd}".format(pid=self.pid, cmd=cmd)
def ns_cmd_output(self, cmd):
def ns_check_cmd(self, cmd):
if isinstance(cmd, list):
cmd = " ".join(cmd)
args = self._ns_args(cmd)
logging.info("ns cmd: %s", args)
return utils.cmd_output(args)
return utils.check_cmd(args)
def copy_file(self, source, destination):
if destination[0] != "/":
@ -72,9 +70,7 @@ class LxdClient(object):
args = "lxc file push {source} {name}/{destination}".format(
source=source, name=self.name, destination=destination
)
status, output = utils.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
utils.check_cmd(args)
class LxcNode(CoreNode):
@ -144,16 +140,6 @@ class LxcNode(CoreNode):
self.client.stop_container()
self.up = False
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]
"""
return self.client.cmd_output(args)
def check_cmd(self, args):
"""
Runs shell command on node.
@ -163,15 +149,12 @@ class LxcNode(CoreNode):
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.client.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return output
return self.client.check_cmd(args)
def node_net_cmd(self, args):
def node_net_cmd(self, args, wait=True):
if not self.up:
logging.debug("node down, not running network command: %s", args)
return 0
return ""
return self.check_cmd(args)
def termcmdstring(self, sh="/bin/sh"):

View file

@ -4,7 +4,6 @@ PhysicalNode class for including real systems in the emulated network.
import logging
import os
import subprocess
import threading
from core import constants, utils
@ -52,20 +51,6 @@ class PhysicalNode(CoreNodeBase):
"""
return sh
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]
"""
os.chdir(self.nodedir)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
status = p.wait()
return status, stdout.strip()
def check_cmd(self, args):
"""
Runs shell command on node.
@ -75,10 +60,8 @@ class PhysicalNode(CoreNodeBase):
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return output.strip()
os.chdir(self.nodedir)
return utils.check_cmd(args)
def shcmd(self, cmdstr, sh="/bin/sh"):
return self.node_net_cmd([sh, "-c", cmdstr])
@ -526,27 +509,6 @@ class Rj45Node(CoreNodeBase, CoreInterface):
"""
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.

View file

@ -415,9 +415,11 @@ class HttpService(UtilService):
Detect the apache2 version using the 'a2query' command.
"""
try:
status, result = utils.cmd_output(["a2query", "-v"])
except CoreCommandError:
status = -1
result = utils.check_cmd(["a2query", "-v"])
status = 0
except CoreCommandError as e:
status = e.returncode
result = e.stderr
if status == 0 and result[:3] == "2.4":
return cls.APACHEVER24

View file

@ -207,27 +207,6 @@ def mute_detach(args, **kwargs):
return subprocess.Popen(args, **kwargs).pid
def cmd_output(args):
"""
Execute a command on the host and return a tuple containing the exit status and
result string. stderr output is folded into the stdout result string.
:param list[str]|str args: command arguments
:return: command status and stdout
:rtype: tuple[int, str]
:raises CoreCommandError: when the file to execute is not found
"""
args = split_args(args)
logging.debug("command: %s", args)
try:
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
status = p.wait()
return status, stdout.decode("utf-8").strip()
except OSError:
raise CoreCommandError(-1, args)
def check_cmd(args, **kwargs):
"""
Execute a command on the host and return a tuple containing the exit status and

View file

@ -108,15 +108,11 @@ class TestCore:
# check various command using vcmd module
command = ["ls"]
status, output = client.cmd_output(command)
assert not status
p, stdin, stdout, stderr = client.popen(command)
assert not p.wait()
assert not client.icmd(command)
# check various command using command line
status, output = client.cmd_output(command)
assert not status
p, stdin, stdout, stderr = client.popen(command)
assert not p.wait()
assert not client.icmd(command)