updates to grpc add_link to return created interface data
This commit is contained in:
parent
0d3460e2ec
commit
71aeb98bb9
7 changed files with 77 additions and 19 deletions
|
@ -2,6 +2,8 @@ import logging
|
|||
import time
|
||||
from typing import Any, Dict, List, Tuple, Type
|
||||
|
||||
import netaddr
|
||||
|
||||
from core import utils
|
||||
from core.api.grpc import common_pb2, core_pb2
|
||||
from core.config import ConfigurableOptions
|
||||
|
@ -10,6 +12,7 @@ from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
|||
from core.emulator.enumerations import LinkTypes, NodeTypes
|
||||
from core.emulator.session import Session
|
||||
from core.nodes.base import CoreNetworkBase, NodeBase
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.services.coreservices import CoreService
|
||||
|
||||
WORKERS = 10
|
||||
|
@ -397,3 +400,40 @@ def get_service_configuration(service: Type[CoreService]) -> core_pb2.NodeServic
|
|||
shutdown=service.shutdown,
|
||||
meta=service.meta,
|
||||
)
|
||||
|
||||
|
||||
def interface_to_proto(interface: CoreInterface) -> core_pb2.Interface:
|
||||
"""
|
||||
Convenience for converting a core interface to the protobuf representation.
|
||||
:param interface: interface to convert
|
||||
:return: interface proto
|
||||
"""
|
||||
net_id = None
|
||||
if interface.net:
|
||||
net_id = interface.net.id
|
||||
ip4 = None
|
||||
ip4mask = None
|
||||
ip6 = None
|
||||
ip6mask = None
|
||||
for addr in interface.addrlist:
|
||||
network = netaddr.IPNetwork(addr)
|
||||
mask = network.prefixlen
|
||||
ip = str(network.ip)
|
||||
if netaddr.valid_ipv4(ip) and not ip4:
|
||||
ip4 = ip
|
||||
ip4mask = mask
|
||||
elif netaddr.valid_ipv6(ip) and not ip6:
|
||||
ip6 = ip
|
||||
ip6mask = mask
|
||||
return core_pb2.Interface(
|
||||
id=interface.netindex,
|
||||
netid=net_id,
|
||||
name=interface.name,
|
||||
mac=str(interface.hwaddr),
|
||||
mtu=interface.mtu,
|
||||
flowid=interface.flow_id,
|
||||
ip4=ip4,
|
||||
ip4mask=ip4mask,
|
||||
ip6=ip6,
|
||||
ip6mask=ip6mask,
|
||||
)
|
||||
|
|
|
@ -637,17 +637,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
interfaces = []
|
||||
for interface_id in node._netif:
|
||||
interface = node._netif[interface_id]
|
||||
net_id = None
|
||||
if interface.net:
|
||||
net_id = interface.net.id
|
||||
interface_proto = core_pb2.Interface(
|
||||
id=interface_id,
|
||||
netid=net_id,
|
||||
name=interface.name,
|
||||
mac=str(interface.hwaddr),
|
||||
mtu=interface.mtu,
|
||||
flowid=interface.flow_id,
|
||||
)
|
||||
interface_proto = grpcutils.interface_to_proto(interface)
|
||||
interfaces.append(interface_proto)
|
||||
|
||||
emane_model = None
|
||||
|
@ -795,10 +785,20 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
node_one_id = request.link.node_one_id
|
||||
node_two_id = request.link.node_two_id
|
||||
interface_one, interface_two, options = grpcutils.add_link_data(request.link)
|
||||
session.add_link(
|
||||
node_one_interface, node_two_interface = session.add_link(
|
||||
node_one_id, node_two_id, interface_one, interface_two, link_options=options
|
||||
)
|
||||
return core_pb2.AddLinkResponse(result=True)
|
||||
interface_one_proto = None
|
||||
interface_two_proto = None
|
||||
if node_one_interface:
|
||||
interface_one_proto = grpcutils.interface_to_proto(node_one_interface)
|
||||
if node_two_interface:
|
||||
interface_two_proto = grpcutils.interface_to_proto(node_two_interface)
|
||||
return core_pb2.AddLinkResponse(
|
||||
result=True,
|
||||
interface_one=interface_one_proto,
|
||||
interface_two=interface_two_proto,
|
||||
)
|
||||
|
||||
def EditLink(
|
||||
self, request: core_pb2.EditLinkRequest, context: ServicerContext
|
||||
|
|
|
@ -42,7 +42,7 @@ from core.location.event import EventLoop
|
|||
from core.location.mobility import BasicRangeModel, MobilityManager
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode, CoreNodeBase, NodeBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.interface import GreTap
|
||||
from core.nodes.interface import CoreInterface, GreTap
|
||||
from core.nodes.lxd import LxcNode
|
||||
from core.nodes.network import (
|
||||
CtrlNet,
|
||||
|
@ -301,7 +301,7 @@ class Session:
|
|||
interface_one: InterfaceData = None,
|
||||
interface_two: InterfaceData = None,
|
||||
link_options: LinkOptions = None,
|
||||
) -> None:
|
||||
) -> Tuple[CoreInterface, CoreInterface]:
|
||||
"""
|
||||
Add a link between nodes.
|
||||
|
||||
|
@ -313,7 +313,7 @@ class Session:
|
|||
data, defaults to none
|
||||
:param link_options: data for creating link,
|
||||
defaults to no options
|
||||
:return: nothing
|
||||
:return: tuple of created core interfaces, depending on link
|
||||
"""
|
||||
if not link_options:
|
||||
link_options = LinkOptions()
|
||||
|
@ -328,6 +328,9 @@ class Session:
|
|||
if node_two:
|
||||
node_two.lock.acquire()
|
||||
|
||||
node_one_interface = None
|
||||
node_two_interface = None
|
||||
|
||||
try:
|
||||
# wireless link
|
||||
if link_options.type == LinkTypes.WIRELESS:
|
||||
|
@ -353,6 +356,7 @@ class Session:
|
|||
net_one.name,
|
||||
)
|
||||
interface = create_interface(node_one, net_one, interface_one)
|
||||
node_one_interface = interface
|
||||
link_config(net_one, interface, link_options)
|
||||
|
||||
# network to node
|
||||
|
@ -363,6 +367,7 @@ class Session:
|
|||
net_one.name,
|
||||
)
|
||||
interface = create_interface(node_two, net_one, interface_two)
|
||||
node_two_interface = interface
|
||||
if not link_options.unidirectional:
|
||||
link_config(net_one, interface, link_options)
|
||||
|
||||
|
@ -374,6 +379,7 @@ class Session:
|
|||
net_two.name,
|
||||
)
|
||||
interface = net_one.linknet(net_two)
|
||||
node_one_interface = interface
|
||||
link_config(net_one, interface, link_options)
|
||||
|
||||
if not link_options.unidirectional:
|
||||
|
@ -426,6 +432,8 @@ class Session:
|
|||
if node_two:
|
||||
node_two.lock.release()
|
||||
|
||||
return node_one_interface, node_two_interface
|
||||
|
||||
def delete_link(
|
||||
self,
|
||||
node_one_id: int,
|
||||
|
|
|
@ -738,6 +738,9 @@ class CoreNode(CoreNodeBase):
|
|||
flow_id = self.node_net_client.get_ifindex(veth.name)
|
||||
veth.flow_id = int(flow_id)
|
||||
logging.debug("interface flow index: %s - %s", veth.name, veth.flow_id)
|
||||
hwaddr = self.node_net_client.get_mac(veth.name)
|
||||
logging.debug("interface mac: %s - %s", veth.name, hwaddr)
|
||||
veth.sethwaddr(hwaddr)
|
||||
|
||||
try:
|
||||
# add network interface to the node. If unsuccessful, destroy the
|
||||
|
|
|
@ -454,6 +454,8 @@ message AddLinkRequest {
|
|||
|
||||
message AddLinkResponse {
|
||||
bool result = 1;
|
||||
Interface interface_one = 2;
|
||||
Interface interface_two = 3;
|
||||
}
|
||||
|
||||
message EditLinkRequest {
|
||||
|
|
|
@ -19,6 +19,7 @@ from core.emulator.emudata import IpPrefixes
|
|||
from core.emulator.enumerations import EventTypes
|
||||
from core.emulator.session import Session
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.netclient import LinuxNetClient
|
||||
|
||||
EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward"
|
||||
|
||||
|
@ -27,8 +28,8 @@ class PatchManager:
|
|||
def __init__(self):
|
||||
self.patches = []
|
||||
|
||||
def patch_obj(self, _cls, attribute):
|
||||
p = mock.patch.object(_cls, attribute)
|
||||
def patch_obj(self, _cls, attribute, return_value=None):
|
||||
p = mock.patch.object(_cls, attribute, return_value=return_value)
|
||||
p.start()
|
||||
self.patches.append(p)
|
||||
|
||||
|
@ -51,11 +52,14 @@ class MockServer:
|
|||
@pytest.fixture(scope="session")
|
||||
def patcher(request):
|
||||
patch_manager = PatchManager()
|
||||
patch_manager.patch_obj(DistributedServer, "remote_cmd")
|
||||
patch_manager.patch_obj(DistributedServer, "remote_cmd", return_value="1")
|
||||
if request.config.getoption("mock"):
|
||||
patch_manager.patch("os.mkdir")
|
||||
patch_manager.patch("core.utils.cmd")
|
||||
patch_manager.patch("core.nodes.netclient.get_net_client")
|
||||
patch_manager.patch_obj(
|
||||
LinuxNetClient, "get_mac", return_value="00:00:00:00:00:00"
|
||||
)
|
||||
patch_manager.patch_obj(CoreNode, "nodefile")
|
||||
patch_manager.patch_obj(Session, "write_state")
|
||||
patch_manager.patch_obj(Session, "write_nodes")
|
||||
|
|
|
@ -13,6 +13,7 @@ class TestDistributed:
|
|||
options = NodeOptions()
|
||||
options.server = server_name
|
||||
node = session.add_node(options=options)
|
||||
session.instantiate()
|
||||
|
||||
# then
|
||||
assert node.server is not None
|
||||
|
|
Loading…
Reference in a new issue