updates to grpc add_link to return created interface data

This commit is contained in:
Blake Harnden 2020-02-14 13:18:05 -08:00
parent 0d3460e2ec
commit 71aeb98bb9
7 changed files with 77 additions and 19 deletions

View file

@ -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,
)

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -454,6 +454,8 @@ message AddLinkRequest {
message AddLinkResponse {
bool result = 1;
Interface interface_one = 2;
Interface interface_two = 3;
}
message EditLinkRequest {

View file

@ -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")

View file

@ -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