updated ctrlnets to assign unique addresses per server, fixed ovs command issue for interface specific commands

This commit is contained in:
Blake Harnden 2019-10-16 10:14:36 -07:00
parent 0b8bc7bd13
commit 61a4e228a1
6 changed files with 81 additions and 79 deletions

View file

@ -4,12 +4,9 @@ Defines the base logic for nodes used within core.
import logging
import os
import random
import shutil
import socket
import string
import threading
from builtins import range
from socket import AF_INET, AF_INET6
from core import utils
@ -18,8 +15,8 @@ from core.emulator.data import LinkData, NodeData
from core.emulator.enumerations import LinkTypes, NodeTypes
from core.errors import CoreCommandError
from core.nodes import client, ipaddress
from core.nodes.interface import CoreInterface, TunTap, Veth
from core.nodes.netclient import LinuxNetClient, OvsNetClient
from core.nodes.interface import TunTap, Veth
from core.nodes.netclient import get_net_client
_DEFAULT_MTU = 1500
@ -63,10 +60,8 @@ class NodeBase(object):
self.opaque = None
self.position = Position()
if session.options.get_config("ovs") == "True":
self.net_client = OvsNetClient(self.net_cmd)
else:
self.net_client = LinuxNetClient(self.net_cmd)
use_ovs = session.options.get_config("ovs") == "True"
self.net_client = get_net_client(use_ovs, self.net_cmd)
def startup(self):
"""
@ -461,15 +456,13 @@ class CoreNode(CoreNodeBase):
def create_node_net_client(self, use_ovs):
"""
Create a client for running network orchestration commands.
Create node network client for running network commands within the nodes
container.
:param bool use_ovs: True to use OVS bridges, False for Linux bridge
:return: network client
:param bool use_ovs: True for OVS bridges, False for Linux bridges
:return:node network client
"""
if use_ovs:
return OvsNetClient(self.node_net_cmd)
else:
return LinuxNetClient(self.node_net_cmd)
return get_net_client(use_ovs, self.node_net_cmd)
def alive(self):
"""
@ -675,11 +668,7 @@ class CoreNode(CoreNodeBase):
raise ValueError("interface name (%s) too long" % name)
veth = Veth(
node=self,
name=name,
localname=localname,
start=self.up,
server=self.server,
self.session, self, name, localname, start=self.up, server=self.server
)
if self.up:
@ -732,7 +721,7 @@ class CoreNode(CoreNodeBase):
sessionid = self.session.short_session_id()
localname = "tap%s.%s.%s" % (self.id, ifindex, sessionid)
name = ifname
tuntap = TunTap(node=self, name=name, localname=localname, start=self.up)
tuntap = TunTap(self.session, self, name, localname, start=self.up)
try:
self.addnetif(tuntap, ifindex)
@ -849,35 +838,6 @@ class CoreNode(CoreNodeBase):
self.ifup(ifindex)
return ifindex
def connectnode(self, ifname, othernode, otherifname):
"""
Connect a node.
:param str ifname: name of interface to connect
:param core.nodes.base.CoreNode othernode: node to connect to
:param str otherifname: interface name to connect to
:return: nothing
"""
tmplen = 8
tmp1 = "tmp." + "".join(
[random.choice(string.ascii_lowercase) for _ in range(tmplen)]
)
tmp2 = "tmp." + "".join(
[random.choice(string.ascii_lowercase) for _ in range(tmplen)]
)
self.net_client.create_veth(tmp1, tmp2)
self.net_client.device_ns(tmp1, str(self.pid))
self.node_net_client.device_name(tmp1, ifname)
interface = CoreInterface(node=self, name=ifname, mtu=_DEFAULT_MTU)
self.addnetif(interface, self.newifindex())
self.net_client.device_ns(tmp2, str(othernode.pid))
othernode.node_net_client.device_name(tmp2, otherifname)
other_interface = CoreInterface(
node=othernode, name=otherifname, mtu=_DEFAULT_MTU
)
othernode.addnetif(other_interface, othernode.newifindex())
def addfile(self, srcname, filename):
"""
Add a file.

View file

@ -7,7 +7,7 @@ from core import utils
from core.emulator.enumerations import NodeTypes
from core.errors import CoreCommandError
from core.nodes.base import CoreNode
from core.nodes.netclient import LinuxNetClient, OvsNetClient
from core.nodes.netclient import get_net_client
class DockerClient(object):
@ -107,10 +107,14 @@ class DockerNode(CoreNode):
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)
"""
Create node network client for running network commands within the nodes
container.
:param bool use_ovs: True for OVS bridges, False for Linux bridges
:return:node network client
"""
return get_net_client(use_ovs, self.nsenter_cmd)
def alive(self):
"""

View file

@ -8,7 +8,7 @@ from builtins import int, range
from core import utils
from core.errors import CoreCommandError
from core.nodes.netclient import LinuxNetClient
from core.nodes.netclient import get_net_client
class CoreInterface(object):
@ -16,17 +16,18 @@ class CoreInterface(object):
Base class for network interfaces.
"""
def __init__(self, node, name, mtu, server=None):
def __init__(self, session, node, name, mtu, server=None):
"""
Creates a PyCoreNetIf instance.
:param core.emulator.session.Session session: core session instance
:param core.nodes.base.CoreNode node: node for interface
:param str name: interface name
:param mtu: mtu value
:param int mtu: mtu value
:param core.emulator.distributed.DistributedServer server: remote server node
will run on, default is None for localhost
"""
self.session = session
self.node = node
self.name = name
if not isinstance(mtu, int):
@ -45,7 +46,8 @@ class CoreInterface(object):
# index used to find flow data
self.flow_id = None
self.server = server
self.net_client = LinuxNetClient(self.net_cmd)
use_ovs = session.options.get_config("ovs") == "True"
self.net_client = get_net_client(use_ovs, self.net_cmd)
def net_cmd(self, args, env=None, cwd=None, wait=True):
"""
@ -211,21 +213,24 @@ class Veth(CoreInterface):
Provides virtual ethernet functionality for core nodes.
"""
def __init__(self, node, name, localname, mtu=1500, server=None, start=True):
def __init__(
self, session, node, name, localname, mtu=1500, server=None, start=True
):
"""
Creates a VEth instance.
:param core.emulator.session.Session session: core session instance
:param core.nodes.base.CoreNode node: related core node
:param str name: interface name
:param str localname: interface local name
:param mtu: interface mtu
:param int mtu: interface mtu
:param core.emulator.distributed.DistributedServer server: remote server node
will run on, default is None for localhost
:param bool start: start flag
:raises CoreCommandError: when there is a command exception
"""
# note that net arg is ignored
CoreInterface.__init__(self, node, name, mtu, server)
CoreInterface.__init__(self, session, node, name, mtu, server)
self.localname = localname
self.up = False
if start:
@ -271,19 +276,22 @@ class TunTap(CoreInterface):
TUN/TAP virtual device in TAP mode
"""
def __init__(self, node, name, localname, mtu=1500, server=None, start=True):
def __init__(
self, session, node, name, localname, mtu=1500, server=None, start=True
):
"""
Create a TunTap instance.
:param core.emulator.session.Session session: core session instance
:param core.nodes.base.CoreNode node: related core node
:param str name: interface name
:param str localname: local interface name
:param mtu: interface mtu
:param int mtu: interface mtu
:param core.emulator.distributed.DistributedServer server: remote server node
will run on, default is None for localhost
:param bool start: start flag
"""
CoreInterface.__init__(self, node, name, mtu, server)
CoreInterface.__init__(self, session, node, name, mtu, server)
self.localname = localname
self.up = False
self.transport_type = "virtual"
@ -466,8 +474,7 @@ class GreTap(CoreInterface):
will run on, default is None for localhost
:raises CoreCommandError: when there is a command exception
"""
CoreInterface.__init__(self, node, name, mtu, server)
self.session = session
CoreInterface.__init__(self, session, node, name, mtu, server)
if _id is None:
# from PyCoreObj
_id = ((id(self) >> 16) ^ (id(self) & 0xFFFF)) & 0xFFFF

View file

@ -7,6 +7,20 @@ import os
from core.constants import BRCTL_BIN, ETHTOOL_BIN, IP_BIN, OVS_BIN, TC_BIN
def get_net_client(use_ovs, run):
"""
Retrieve desired net client for running network commands.
:param bool use_ovs: True for OVS bridges, False for Linux bridges
:param func run: function used to run net client commands
:return: net client class
"""
if use_ovs:
return OvsNetClient(run)
else:
return LinuxNetClient(run)
class LinuxNetClient(object):
"""
Client for creating Linux bridges and ip interfaces for nodes.

View file

@ -16,6 +16,7 @@ from core.errors import CoreCommandError, CoreError
from core.nodes import ipaddress
from core.nodes.base import CoreNetworkBase
from core.nodes.interface import GreTap, Veth
from core.nodes.netclient import get_net_client
ebtables_lock = threading.Lock()
@ -558,7 +559,7 @@ class CoreNetwork(CoreNetworkBase):
if len(name) >= 16:
raise ValueError("interface name %s too long" % name)
netif = Veth(node=None, name=name, localname=localname, mtu=1500, start=self.up)
netif = Veth(self.session, None, name, localname, start=self.up)
self.attach(netif)
if net.up:
# this is similar to net.attach() but uses netif.name instead of localname
@ -766,6 +767,24 @@ class CtrlNet(CoreNetwork):
self.serverintf = serverintf
CoreNetwork.__init__(self, session, _id, name, start, server)
def add_addresses(self, address):
"""
Add addresses used for created control networks,
:param core.nodes.interfaces.IpAddress address: starting address to use
:return:
"""
use_ovs = self.session.options.get_config("ovs") == "True"
current = "%s/%s" % (address, self.prefix.prefixlen)
net_client = get_net_client(use_ovs, utils.check_cmd)
net_client.create_address(self.brname, current)
for name in self.session.servers:
server = self.session.servers[name]
address -= 1
current = "%s/%s" % (address, self.prefix.prefixlen)
net_client = get_net_client(use_ovs, server.remote_cmd)
net_client.create_address(self.brname, current)
def startup(self):
"""
Startup functionality for the control network.
@ -778,16 +797,14 @@ class CtrlNet(CoreNetwork):
CoreNetwork.startup(self)
if self.hostid:
addr = self.prefix.addr(self.hostid)
else:
addr = self.prefix.max_addr()
logging.info("added control network bridge: %s %s", self.brname, self.prefix)
if self.assign_address:
addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)]
self.addrconfig(addrlist=addrlist)
if self.hostid and self.assign_address:
address = self.prefix.addr(self.hostid)
self.add_addresses(address)
elif self.assign_address:
address = self.prefix.max_addr()
self.add_addresses(address)
if self.updown_script:
logging.info(

View file

@ -246,7 +246,7 @@ class Rj45Node(CoreNodeBase, CoreInterface):
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)
CoreInterface.__init__(self, session, self, name, mtu, server)
self.up = False
self.lock = threading.RLock()
self.ifindex = None