diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 49cf4f24..90ca9dfe 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -152,8 +152,13 @@ class EmaneManager(ModelManager): """ try: # check for emane - emane_version = utils.check_cmd(["emane", "--version"]) + args = ["emane", "--version"] + emane_version = utils.check_cmd(args) logging.info("using EMANE: %s", emane_version) + args = " ".join(args) + for server in self.session.servers: + conn = self.session.servers[server] + distributed.remote_cmd(conn, args) # load default emane models self.load_models(EMANE_MODELS) diff --git a/daemon/core/emulator/session.py b/daemon/core/emulator/session.py index 9bc2ab80..e3a2389b 100644 --- a/daemon/core/emulator/session.py +++ b/daemon/core/emulator/session.py @@ -140,6 +140,11 @@ class Session(object): self.options.set_config(key, value) self.metadata = SessionMetaData() + # distributed servers + self.servers = {} + self.tunnels = {} + self.address = None + # initialize session feature helpers self.broker = CoreBroker(session=self) self.location = CoreLocation() @@ -148,11 +153,6 @@ class Session(object): self.emane = EmaneManager(session=self) self.sdt = Sdt(session=self) - # distributed servers - self.servers = {} - self.tunnels = {} - self.address = None - # initialize default node services self.services.default_services = { "mdr": ("zebra", "OSPFv3MDR", "IPForward"), diff --git a/daemon/core/nodes/base.py b/daemon/core/nodes/base.py index 78279b5e..2b9e08eb 100644 --- a/daemon/core/nodes/base.py +++ b/daemon/core/nodes/base.py @@ -84,18 +84,24 @@ class NodeBase(object): """ raise NotImplementedError - def net_cmd(self, args, env=None): + def net_cmd(self, args, env=None, cwd=None, wait=True): """ Runs a command that is used to configure and setup the network on the host system. :param list[str]|str args: command to run :param dict env: environment to run command with + :param str cwd: directory to run command in + :param bool wait: True to wait for status, False otherwise :return: combined stdout and stderr :rtype: str :raises CoreCommandError: when a non-zero exit status occurs """ - raise NotImplementedError + if self.server is None: + return utils.check_cmd(args, env=env, cwd=cwd) + else: + args = " ".join(args) + return distributed.remote_cmd(self.server, args, env, cwd, wait) def setposition(self, x=None, y=None, z=None): """ @@ -381,40 +387,13 @@ class CoreNodeBase(NodeBase): return common - def net_cmd(self, args, env=None): - """ - Runs a command that is used to configure and setup the network on the host - system. - - :param list[str]|str args: command to run - :param dict env: environment to run command with - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - if self.server is None: - return utils.check_cmd(args, env=env) - else: - args = " ".join(args) - return distributed.remote_cmd(self.server, args, env=env) - - def node_net_cmd(self, args): + def node_net_cmd(self, args, wait=True): """ Runs a command that is used to configure and setup the network within a node. :param list[str]|str args: command to run - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - raise NotImplementedError - - def check_cmd(self, args): - """ - Runs shell command on node. - - :param list[str]|str args: command to run + :param bool wait: True to wait for status, False otherwise :return: combined stdout and stderr :rtype: str :raises CoreCommandError: when a non-zero exit status occurs @@ -607,18 +586,6 @@ class CoreNode(CoreNodeBase): args = " ".join(args) return distributed.remote_cmd(self.server, args, wait=wait) - def check_cmd(self, args): - """ - Runs shell command on node. - - :param list[str]|str args: command to run - :param bool wait: True to wait for status, False otherwise - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - return self.client.check_cmd(args) - def termcmdstring(self, sh="/bin/sh"): """ Create a terminal command string. diff --git a/daemon/core/nodes/docker.py b/daemon/core/nodes/docker.py index 028b3e0b..28a92607 100644 --- a/daemon/core/nodes/docker.py +++ b/daemon/core/nodes/docker.py @@ -142,17 +142,6 @@ class DockerNode(CoreNode): self.client.stop_container() self.up = False - def check_cmd(self, args): - """ - Runs shell command on node. - - :param list[str]|str args: command to run - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - return self.client.check_cmd(args) - def node_net_cmd(self, args, wait=True): if not self.up: logging.debug("node down, not running network command: %s", args) @@ -178,7 +167,7 @@ class DockerNode(CoreNode): """ logging.debug("creating node dir: %s", path) args = "mkdir -p {path}".format(path=path) - self.check_cmd(args) + self.client.check_cmd(args) def mount(self, source, target): """ diff --git a/daemon/core/nodes/interface.py b/daemon/core/nodes/interface.py index 8b73b1b7..08f1d662 100644 --- a/daemon/core/nodes/interface.py +++ b/daemon/core/nodes/interface.py @@ -48,12 +48,23 @@ class CoreInterface(object): self.server = server self.net_client = LinuxNetClient(self.net_cmd) - def net_cmd(self, args): + def net_cmd(self, args, env=None, cwd=None, wait=True): + """ + Runs a command on the host system or distributed servers. + + :param list[str]|str args: command to run + :param dict env: environment to run command with + :param str cwd: directory to run command in + :param bool wait: True to wait for status, False otherwise + :return: combined stdout and stderr + :rtype: str + :raises CoreCommandError: when a non-zero exit status occurs + """ if self.server is None: - return utils.check_cmd(args) + return utils.check_cmd(args, env=env, cwd=cwd) else: args = " ".join(args) - return distributed.remote_cmd(self.server, args) + return distributed.remote_cmd(self.server, args, env, cwd, wait) def startup(self): """ diff --git a/daemon/core/nodes/lxd.py b/daemon/core/nodes/lxd.py index c28306b6..f16df715 100644 --- a/daemon/core/nodes/lxd.py +++ b/daemon/core/nodes/lxd.py @@ -140,22 +140,11 @@ class LxcNode(CoreNode): self.client.stop_container() self.up = False - def check_cmd(self, args): - """ - Runs shell command on node. - - :param list[str]|str args: command to run - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - return self.client.check_cmd(args) - def node_net_cmd(self, args, wait=True): if not self.up: logging.debug("node down, not running network command: %s", args) return "" - return self.check_cmd(args) + return self.client.check_cmd(args) def termcmdstring(self, sh="/bin/sh"): """ @@ -175,7 +164,7 @@ class LxcNode(CoreNode): """ logging.info("creating node dir: %s", path) args = "mkdir -p {path}".format(path=path) - self.check_cmd(args) + return self.client.check_cmd(args) def mount(self, source, target): """ diff --git a/daemon/core/nodes/netclient.py b/daemon/core/nodes/netclient.py index 34fee343..a689dde9 100644 --- a/daemon/core/nodes/netclient.py +++ b/daemon/core/nodes/netclient.py @@ -5,7 +5,6 @@ Clients for dealing with bridge/interface commands. import os from core.constants import BRCTL_BIN, ETHTOOL_BIN, IP_BIN, OVS_BIN, TC_BIN -from core.utils import check_cmd class LinuxNetClient(object): @@ -275,7 +274,7 @@ class LinuxNetClient(object): :param str name: bridge name :return: nothing """ - check_cmd([BRCTL_BIN, "setageing", name, "0"]) + self.run([BRCTL_BIN, "setageing", name, "0"]) class OvsNetClient(LinuxNetClient): diff --git a/daemon/core/nodes/network.py b/daemon/core/nodes/network.py index 81dfc34b..b236b96b 100644 --- a/daemon/core/nodes/network.py +++ b/daemon/core/nodes/network.py @@ -308,24 +308,26 @@ class CoreNetwork(CoreNetworkBase): self.startup() ebq.startupdateloop(self) - def net_cmd(self, args, env=None): + def net_cmd(self, args, env=None, cwd=None, wait=True): """ Runs a command that is used to configure and setup the network on the host system and all configured distributed servers. :param list[str]|str args: command to run :param dict env: environment to run command with + :param str cwd: directory to run command in + :param bool wait: True to wait for status, False otherwise :return: combined stdout and stderr :rtype: str :raises CoreCommandError: when a non-zero exit status occurs """ logging.info("network node(%s) cmd", self.name) - output = utils.check_cmd(args, env=env) + output = utils.check_cmd(args, env=env, cwd=cwd) args = " ".join(args) for server in self.session.servers: conn = self.session.servers[server] - distributed.remote_cmd(conn, args, env=env) + distributed.remote_cmd(conn, args, env, cwd, wait) return output diff --git a/daemon/core/nodes/physical.py b/daemon/core/nodes/physical.py index 60e445ea..4c219258 100644 --- a/daemon/core/nodes/physical.py +++ b/daemon/core/nodes/physical.py @@ -51,21 +51,6 @@ class PhysicalNode(CoreNodeBase): """ return sh - def check_cmd(self, args): - """ - Runs shell command on node. - - :param list[str]|str args: command to run - :return: combined stdout and stderr - :rtype: str - :raises CoreCommandError: when a non-zero exit status occurs - """ - os.chdir(self.nodedir) - return utils.check_cmd(args) - - def shcmd(self, cmdstr, sh="/bin/sh"): - return self.node_net_cmd([sh, "-c", cmdstr]) - def sethwaddr(self, ifindex, addr): """ Set hardware address for an interface. @@ -205,13 +190,13 @@ class PhysicalNode(CoreNodeBase): source = os.path.abspath(source) logging.info("mounting %s at %s", source, target) os.makedirs(target) - self.check_cmd([constants.MOUNT_BIN, "--bind", source, target]) + self.net_cmd([constants.MOUNT_BIN, "--bind", source, target], cwd=self.nodedir) self._mounts.append((source, target)) def umount(self, target): logging.info("unmounting '%s'" % target) try: - self.check_cmd([constants.UMOUNT_BIN, "-l", target]) + self.net_cmd([constants.UMOUNT_BIN, "-l", target], cwd=self.nodedir) except CoreCommandError: logging.exception("unmounting failed for %s", target) @@ -256,7 +241,8 @@ class Rj45Node(CoreNodeBase, CoreInterface): :param str name: node name :param mtu: rj45 mtu :param bool start: start flag - :param str server: remote server node will run on, default is None for localhost + :param fabric.connection.Connection server: remote server node will run on, + default is None for localhost """ CoreNodeBase.__init__(self, session, _id, name, start, server) CoreInterface.__init__(self, node=self, name=name, mtu=mtu) @@ -498,17 +484,6 @@ class Rj45Node(CoreNodeBase, CoreInterface): CoreInterface.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 CoreCommandError: when a non-zero exit status occurs - """ - raise NotImplementedError - def termcmdstring(self, sh): """ Create a terminal command string. diff --git a/daemon/core/services/coreservices.py b/daemon/core/services/coreservices.py index d6eeb1b5..dc45fa33 100644 --- a/daemon/core/services/coreservices.py +++ b/daemon/core/services/coreservices.py @@ -631,8 +631,9 @@ class CoreServices(object): """ status = 0 for args in service.shutdown: + args = utils.split_args(args) try: - node.check_cmd(args) + node.node_net_cmd(args) except CoreCommandError: logging.exception("error running stop command %s", args) status = -1 diff --git a/daemon/tests/test_nodes.py b/daemon/tests/test_nodes.py index baf0c20c..ad5476d4 100644 --- a/daemon/tests/test_nodes.py +++ b/daemon/tests/test_nodes.py @@ -30,7 +30,7 @@ class TestNodes: assert os.path.exists(node.nodedir) assert node.alive() assert node.up - assert node.check_cmd(["ip", "addr", "show", "lo"]) + assert node.node_net_cmd(["ip", "addr", "show", "lo"]) def test_node_update(self, session): # given