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