updates to lxd/docker to work with net_cmd/node_net_cmd
This commit is contained in:
parent
82bdbd776b
commit
5f282bb695
5 changed files with 122 additions and 72 deletions
|
@ -452,14 +452,24 @@ class CoreNode(CoreNodeBase):
|
|||
self._mounts = []
|
||||
self.bootsh = bootsh
|
||||
|
||||
if session.options.get_config("ovs") == "True":
|
||||
self.node_net_client = OvsNetClient(self.node_net_cmd)
|
||||
else:
|
||||
self.node_net_client = LinuxNetClient(self.node_net_cmd)
|
||||
use_ovs = session.options.get_config("ovs") == "True"
|
||||
self.node_net_client = self.create_node_net_client(use_ovs)
|
||||
|
||||
if start:
|
||||
self.startup()
|
||||
|
||||
def create_node_net_client(self, use_ovs):
|
||||
"""
|
||||
Create a client for running network orchestration commands.
|
||||
|
||||
:param bool use_ovs: True to use OVS bridges, False for Linux bridge
|
||||
:return: network client
|
||||
"""
|
||||
if use_ovs:
|
||||
return OvsNetClient(self.node_net_cmd)
|
||||
else:
|
||||
return LinuxNetClient(self.node_net_cmd)
|
||||
|
||||
def alive(self):
|
||||
"""
|
||||
Check if the node is alive.
|
||||
|
@ -584,7 +594,7 @@ class CoreNode(CoreNodeBase):
|
|||
:param str sh: shell to execute command in
|
||||
:return: str
|
||||
"""
|
||||
return self.client.termcmdstring(sh)
|
||||
return self.client.create_cmd(sh)
|
||||
|
||||
def privatedir(self, path):
|
||||
"""
|
||||
|
|
|
@ -4,7 +4,7 @@ over a control channel to the vnoded process running in a network namespace.
|
|||
The control channel can be accessed via calls using the vcmd shell.
|
||||
"""
|
||||
|
||||
from core import constants, utils
|
||||
from core import utils
|
||||
from core.constants import VCMD_BIN
|
||||
|
||||
|
||||
|
@ -66,12 +66,3 @@ class VnodeClient(object):
|
|||
self._verify_connection()
|
||||
args = self.create_cmd(args)
|
||||
return utils.check_cmd(args, wait=wait)
|
||||
|
||||
def termcmdstring(self, sh="/bin/sh"):
|
||||
"""
|
||||
Create a terminal command string.
|
||||
|
||||
:param str sh: shell to execute command in
|
||||
:return: str
|
||||
"""
|
||||
return "%s -c %s -- %s" % (constants.VCMD_BIN, self.ctrlchnlname, sh)
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from core import utils
|
||||
from core.emulator import distributed
|
||||
from core.emulator.enumerations import NodeTypes
|
||||
from core.errors import CoreCommandError
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.netclient import LinuxNetClient, OvsNetClient
|
||||
|
||||
|
||||
class DockerClient(object):
|
||||
def __init__(self, name, image):
|
||||
def __init__(self, name, image, run):
|
||||
self.name = name
|
||||
self.image = image
|
||||
self.run = run
|
||||
self.pid = None
|
||||
|
||||
def create_container(self):
|
||||
utils.check_cmd(
|
||||
self.run(
|
||||
"docker run -td --init --net=none --hostname {name} --name {name} "
|
||||
"--sysctl net.ipv6.conf.all.disable_ipv6=0 "
|
||||
"{image} /bin/bash".format(
|
||||
|
@ -27,7 +31,7 @@ class DockerClient(object):
|
|||
|
||||
def get_info(self):
|
||||
args = "docker inspect {name}".format(name=self.name)
|
||||
output = utils.check_cmd(args)
|
||||
output = self.run(args)
|
||||
data = json.loads(output)
|
||||
if not data:
|
||||
raise CoreCommandError(
|
||||
|
@ -43,22 +47,24 @@ class DockerClient(object):
|
|||
return False
|
||||
|
||||
def stop_container(self):
|
||||
utils.check_cmd("docker rm -f {name}".format(
|
||||
self.run("docker rm -f {name}".format(
|
||||
name=self.name
|
||||
))
|
||||
|
||||
def check_cmd(self, cmd):
|
||||
if isinstance(cmd, list):
|
||||
cmd = " ".join(cmd)
|
||||
logging.info("docker cmd output: %s", cmd)
|
||||
return utils.check_cmd("docker exec {name} {cmd}".format(
|
||||
name=self.name,
|
||||
cmd=cmd
|
||||
))
|
||||
|
||||
def create_ns_cmd(self, cmd):
|
||||
return "nsenter -t {pid} -u -i -p -n {cmd}".format(
|
||||
pid=self.pid,
|
||||
cmd=cmd
|
||||
)
|
||||
|
||||
def ns_cmd(self, cmd, wait):
|
||||
if isinstance(cmd, list):
|
||||
cmd = " ".join(cmd)
|
||||
args = "nsenter -t {pid} -u -i -p -n {cmd}".format(
|
||||
pid=self.pid,
|
||||
cmd=cmd
|
||||
|
@ -67,7 +73,7 @@ class DockerClient(object):
|
|||
|
||||
def get_pid(self):
|
||||
args = "docker inspect -f '{{{{.State.Pid}}}}' {name}".format(name=self.name)
|
||||
output = utils.check_cmd(args)
|
||||
output = self.run(args)
|
||||
self.pid = output
|
||||
logging.debug("node(%s) pid: %s", self.name, self.pid)
|
||||
return output
|
||||
|
@ -78,7 +84,7 @@ class DockerClient(object):
|
|||
name=self.name,
|
||||
destination=destination
|
||||
)
|
||||
return utils.check_cmd(args)
|
||||
return self.run(args)
|
||||
|
||||
|
||||
class DockerNode(CoreNode):
|
||||
|
@ -101,6 +107,12 @@ class DockerNode(CoreNode):
|
|||
self.image = image
|
||||
super(DockerNode, self).__init__(session, _id, name, nodedir, bootsh, start)
|
||||
|
||||
def create_node_net_client(self, use_ovs):
|
||||
if use_ovs:
|
||||
return OvsNetClient(self.nsenter_cmd)
|
||||
else:
|
||||
return LinuxNetClient(self.nsenter_cmd)
|
||||
|
||||
def alive(self):
|
||||
"""
|
||||
Check if the node is alive.
|
||||
|
@ -122,7 +134,7 @@ class DockerNode(CoreNode):
|
|||
if self.up:
|
||||
raise ValueError("starting a node that is already up")
|
||||
self.makenodedir()
|
||||
self.client = DockerClient(self.name, self.image)
|
||||
self.client = DockerClient(self.name, self.image, self.net_cmd)
|
||||
self.pid = self.client.create_container()
|
||||
self.up = True
|
||||
|
||||
|
@ -141,12 +153,13 @@ class DockerNode(CoreNode):
|
|||
self.client.stop_container()
|
||||
self.up = False
|
||||
|
||||
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.client.ns_cmd(args, wait)
|
||||
def nsenter_cmd(self, args, wait=True):
|
||||
if self.server is None:
|
||||
args = self.client.create_ns_cmd(args)
|
||||
return utils.check_cmd(args, wait=wait)
|
||||
else:
|
||||
args = self.client.create_ns_cmd(args)
|
||||
return distributed.remote_cmd(self.server, args, wait=wait)
|
||||
|
||||
def termcmdstring(self, sh="/bin/sh"):
|
||||
"""
|
||||
|
@ -166,7 +179,7 @@ class DockerNode(CoreNode):
|
|||
"""
|
||||
logging.debug("creating node dir: %s", path)
|
||||
args = "mkdir -p {path}".format(path=path)
|
||||
self.client.check_cmd(args)
|
||||
self.node_net_cmd(args)
|
||||
|
||||
def mount(self, source, target):
|
||||
"""
|
||||
|
@ -189,13 +202,24 @@ class DockerNode(CoreNode):
|
|||
:param int mode: mode for file
|
||||
:return: nothing
|
||||
"""
|
||||
logging.debug("node dir(%s) ctrlchannel(%s)", self.nodedir, self.ctrlchnlname)
|
||||
logging.debug("nodefile filename(%s) mode(%s)", filename, mode)
|
||||
file_path = os.path.join(self.nodedir, filename)
|
||||
with open(file_path, "w") as f:
|
||||
os.chmod(f.name, mode)
|
||||
f.write(contents)
|
||||
self.client.copy_file(file_path, filename)
|
||||
directory = os.path.dirname(filename)
|
||||
temp = NamedTemporaryFile(delete=False)
|
||||
temp.write(contents.encode("utf-8"))
|
||||
temp.close()
|
||||
|
||||
if directory:
|
||||
self.node_net_cmd("mkdir -m %o -p %s" % (0o755, directory))
|
||||
if self.server is not None:
|
||||
distributed.remote_put(self.server, temp.name, temp.name)
|
||||
self.client.copy_file(temp.name, filename)
|
||||
self.node_net_cmd("chmod %o %s" % (mode, filename))
|
||||
if self.server is not None:
|
||||
self.net_cmd("rm -f %s" % temp.name)
|
||||
os.unlink(temp.name)
|
||||
logging.debug(
|
||||
"node(%s) added file: %s; mode: 0%o", self.name, filename, mode
|
||||
)
|
||||
|
||||
def nodefilecopy(self, filename, srcfilename, mode=None):
|
||||
"""
|
||||
|
@ -207,5 +231,18 @@ class DockerNode(CoreNode):
|
|||
:param int mode: mode to copy to
|
||||
:return: nothing
|
||||
"""
|
||||
logging.info("node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode)
|
||||
raise Exception("not supported")
|
||||
logging.info(
|
||||
"node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode
|
||||
)
|
||||
directory = os.path.dirname(filename)
|
||||
self.node_net_cmd("mkdir -p %s" % directory)
|
||||
|
||||
if self.server is None:
|
||||
source = srcfilename
|
||||
else:
|
||||
temp = NamedTemporaryFile(delete=False)
|
||||
source = temp.name
|
||||
distributed.remote_put(self.server, source, temp.name)
|
||||
|
||||
self.client.copy_file(source, filename)
|
||||
self.node_net_cmd("chmod %o %s" % (mode, filename))
|
||||
|
|
|
@ -2,30 +2,31 @@ import json
|
|||
import logging
|
||||
import os
|
||||
import time
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from core import utils
|
||||
from core.emulator import distributed
|
||||
from core.emulator.enumerations import NodeTypes
|
||||
from core.errors import CoreCommandError
|
||||
from core.nodes.base import CoreNode
|
||||
|
||||
|
||||
class LxdClient(object):
|
||||
def __init__(self, name, image):
|
||||
def __init__(self, name, image, run):
|
||||
self.name = name
|
||||
self.image = image
|
||||
self.run = run
|
||||
self.pid = None
|
||||
|
||||
def create_container(self):
|
||||
utils.check_cmd(
|
||||
"lxc launch {image} {name}".format(name=self.name, image=self.image)
|
||||
)
|
||||
self.run("lxc launch {image} {name}".format(name=self.name, image=self.image))
|
||||
data = self.get_info()
|
||||
self.pid = data["state"]["pid"]
|
||||
return self.pid
|
||||
|
||||
def get_info(self):
|
||||
args = "lxc list {name} --format json".format(name=self.name)
|
||||
output = utils.check_cmd(args)
|
||||
output = self.run(args)
|
||||
data = json.loads(output)
|
||||
if not data:
|
||||
raise CoreCommandError(
|
||||
|
@ -41,20 +42,16 @@ class LxdClient(object):
|
|||
return False
|
||||
|
||||
def stop_container(self):
|
||||
utils.check_cmd("lxc delete --force {name}".format(name=self.name))
|
||||
self.run("lxc delete --force {name}".format(name=self.name))
|
||||
|
||||
def create_cmd(self, cmd):
|
||||
return "lxc exec -nT {name} -- {cmd}".format(name=self.name, cmd=cmd)
|
||||
|
||||
def check_cmd(self, cmd, wait=True):
|
||||
args = self.create_cmd(cmd)
|
||||
return utils.check_cmd(args, wait=wait)
|
||||
|
||||
def create_ns_cmd(self, cmd):
|
||||
return "nsenter -t {pid} -m -u -i -p -n {cmd}".format(pid=self.pid, cmd=cmd)
|
||||
|
||||
def ns_check_cmd(self, cmd, wait=True):
|
||||
args = self.create_ns_cmd(cmd)
|
||||
def check_cmd(self, cmd, wait=True):
|
||||
args = self.create_cmd(cmd)
|
||||
return utils.check_cmd(args, wait=wait)
|
||||
|
||||
def copy_file(self, source, destination):
|
||||
|
@ -64,7 +61,7 @@ class LxdClient(object):
|
|||
args = "lxc file push {source} {name}/{destination}".format(
|
||||
source=source, name=self.name, destination=destination
|
||||
)
|
||||
utils.check_cmd(args)
|
||||
self.run(args)
|
||||
|
||||
|
||||
class LxcNode(CoreNode):
|
||||
|
@ -115,7 +112,7 @@ class LxcNode(CoreNode):
|
|||
if self.up:
|
||||
raise ValueError("starting a node that is already up")
|
||||
self.makenodedir()
|
||||
self.client = LxdClient(self.name, self.image)
|
||||
self.client = LxdClient(self.name, self.image, self.net_cmd)
|
||||
self.pid = self.client.create_container()
|
||||
self.up = True
|
||||
|
||||
|
@ -134,12 +131,6 @@ class LxcNode(CoreNode):
|
|||
self.client.stop_container()
|
||||
self.up = False
|
||||
|
||||
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.client.check_cmd(args, wait)
|
||||
|
||||
def termcmdstring(self, sh="/bin/sh"):
|
||||
"""
|
||||
Create a terminal command string.
|
||||
|
@ -147,7 +138,7 @@ class LxcNode(CoreNode):
|
|||
:param str sh: shell to execute command in
|
||||
:return: str
|
||||
"""
|
||||
return "lxc exec {name} -- bash".format(name=self.name)
|
||||
return "lxc exec {name} -- {sh}".format(name=self.name, sh=sh)
|
||||
|
||||
def privatedir(self, path):
|
||||
"""
|
||||
|
@ -158,7 +149,7 @@ class LxcNode(CoreNode):
|
|||
"""
|
||||
logging.info("creating node dir: %s", path)
|
||||
args = "mkdir -p {path}".format(path=path)
|
||||
return self.client.check_cmd(args)
|
||||
return self.node_net_cmd(args)
|
||||
|
||||
def mount(self, source, target):
|
||||
"""
|
||||
|
@ -181,13 +172,23 @@ class LxcNode(CoreNode):
|
|||
:param int mode: mode for file
|
||||
:return: nothing
|
||||
"""
|
||||
logging.debug("node dir(%s) ctrlchannel(%s)", self.nodedir, self.ctrlchnlname)
|
||||
logging.debug("nodefile filename(%s) mode(%s)", filename, mode)
|
||||
file_path = os.path.join(self.nodedir, filename)
|
||||
with open(file_path, "w") as f:
|
||||
os.chmod(f.name, mode)
|
||||
f.write(contents)
|
||||
self.client.copy_file(file_path, filename)
|
||||
|
||||
directory = os.path.dirname(filename)
|
||||
temp = NamedTemporaryFile(delete=False)
|
||||
temp.write(contents.encode("utf-8"))
|
||||
temp.close()
|
||||
|
||||
if directory:
|
||||
self.node_net_cmd("mkdir -m %o -p %s" % (0o755, directory))
|
||||
if self.server is not None:
|
||||
distributed.remote_put(self.server, temp.name, temp.name)
|
||||
self.client.copy_file(temp.name, filename)
|
||||
self.node_net_cmd("chmod %o %s" % (mode, filename))
|
||||
if self.server is not None:
|
||||
self.net_cmd("rm -f %s" % temp.name)
|
||||
os.unlink(temp.name)
|
||||
logging.debug("node(%s) added file: %s; mode: 0%o", self.name, filename, mode)
|
||||
|
||||
def nodefilecopy(self, filename, srcfilename, mode=None):
|
||||
"""
|
||||
|
@ -202,7 +203,18 @@ class LxcNode(CoreNode):
|
|||
logging.info(
|
||||
"node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode
|
||||
)
|
||||
raise Exception("not supported")
|
||||
directory = os.path.dirname(filename)
|
||||
self.node_net_cmd("mkdir -p %s" % directory)
|
||||
|
||||
if self.server is None:
|
||||
source = srcfilename
|
||||
else:
|
||||
temp = NamedTemporaryFile(delete=False)
|
||||
source = temp.name
|
||||
distributed.remote_put(self.server, source, temp.name)
|
||||
|
||||
self.client.copy_file(source, filename)
|
||||
self.node_net_cmd("chmod %o %s" % (mode, filename))
|
||||
|
||||
def addnetif(self, netif, ifindex):
|
||||
super(LxcNode, self).addnetif(netif, ifindex)
|
||||
|
|
|
@ -5,7 +5,7 @@ from core.emulator.emudata import IpPrefixes, NodeOptions
|
|||
from core.emulator.enumerations import EventTypes, NodeTypes
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
coreemu = CoreEmu()
|
||||
session = coreemu.create_session()
|
||||
|
@ -14,7 +14,7 @@ if __name__ == "__main__":
|
|||
# create nodes and interfaces
|
||||
try:
|
||||
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
|
||||
options = NodeOptions(image="ubuntu")
|
||||
options = NodeOptions(image="ubuntu:18.04")
|
||||
|
||||
# create node one
|
||||
node_one = session.add_node(_type=NodeTypes.LXC, node_options=options)
|
||||
|
|
Loading…
Add table
Reference in a new issue