updates to layout core module packages in a more logical way, including renaming methods from objects to nodes and nodes.objid to nodes.id

This commit is contained in:
bharnden 2019-04-29 23:31:47 -07:00
parent 9517740704
commit 66e603906a
100 changed files with 10283 additions and 3489 deletions

View file

@ -1,3 +0,0 @@
"""
Contains code specific to the legacy TCP API for interacting with the TCL based GUI.
"""

View file

@ -10,9 +10,9 @@ from contextlib import contextmanager
import grpc import grpc
from core.grpc import core_pb2 from core.api.grpc import core_pb2
from core.grpc import core_pb2_grpc from core.api.grpc import core_pb2_grpc
from core.misc.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
class InterfaceHelper(object): class InterfaceHelper(object):

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,828 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import core_pb2 as core__pb2
class CoreApiStub(object):
# missing associated documentation comment in .proto file
pass
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.CreateSession = channel.unary_unary(
'/core.CoreApi/CreateSession',
request_serializer=core__pb2.CreateSessionRequest.SerializeToString,
response_deserializer=core__pb2.CreateSessionResponse.FromString,
)
self.DeleteSession = channel.unary_unary(
'/core.CoreApi/DeleteSession',
request_serializer=core__pb2.DeleteSessionRequest.SerializeToString,
response_deserializer=core__pb2.DeleteSessionResponse.FromString,
)
self.GetSessions = channel.unary_unary(
'/core.CoreApi/GetSessions',
request_serializer=core__pb2.GetSessionsRequest.SerializeToString,
response_deserializer=core__pb2.GetSessionsResponse.FromString,
)
self.GetSession = channel.unary_unary(
'/core.CoreApi/GetSession',
request_serializer=core__pb2.GetSessionRequest.SerializeToString,
response_deserializer=core__pb2.GetSessionResponse.FromString,
)
self.GetSessionOptions = channel.unary_unary(
'/core.CoreApi/GetSessionOptions',
request_serializer=core__pb2.GetSessionOptionsRequest.SerializeToString,
response_deserializer=core__pb2.GetSessionOptionsResponse.FromString,
)
self.SetSessionOptions = channel.unary_unary(
'/core.CoreApi/SetSessionOptions',
request_serializer=core__pb2.SetSessionOptionsRequest.SerializeToString,
response_deserializer=core__pb2.SetSessionOptionsResponse.FromString,
)
self.GetSessionLocation = channel.unary_unary(
'/core.CoreApi/GetSessionLocation',
request_serializer=core__pb2.GetSessionLocationRequest.SerializeToString,
response_deserializer=core__pb2.GetSessionLocationResponse.FromString,
)
self.SetSessionLocation = channel.unary_unary(
'/core.CoreApi/SetSessionLocation',
request_serializer=core__pb2.SetSessionLocationRequest.SerializeToString,
response_deserializer=core__pb2.SetSessionLocationResponse.FromString,
)
self.SetSessionState = channel.unary_unary(
'/core.CoreApi/SetSessionState',
request_serializer=core__pb2.SetSessionStateRequest.SerializeToString,
response_deserializer=core__pb2.SetSessionStateResponse.FromString,
)
self.NodeEvents = channel.unary_stream(
'/core.CoreApi/NodeEvents',
request_serializer=core__pb2.NodeEventsRequest.SerializeToString,
response_deserializer=core__pb2.NodeEvent.FromString,
)
self.LinkEvents = channel.unary_stream(
'/core.CoreApi/LinkEvents',
request_serializer=core__pb2.LinkEventsRequest.SerializeToString,
response_deserializer=core__pb2.LinkEvent.FromString,
)
self.SessionEvents = channel.unary_stream(
'/core.CoreApi/SessionEvents',
request_serializer=core__pb2.SessionEventsRequest.SerializeToString,
response_deserializer=core__pb2.SessionEvent.FromString,
)
self.ConfigEvents = channel.unary_stream(
'/core.CoreApi/ConfigEvents',
request_serializer=core__pb2.ConfigEventsRequest.SerializeToString,
response_deserializer=core__pb2.ConfigEvent.FromString,
)
self.ExceptionEvents = channel.unary_stream(
'/core.CoreApi/ExceptionEvents',
request_serializer=core__pb2.ExceptionEventsRequest.SerializeToString,
response_deserializer=core__pb2.ExceptionEvent.FromString,
)
self.FileEvents = channel.unary_stream(
'/core.CoreApi/FileEvents',
request_serializer=core__pb2.FileEventsRequest.SerializeToString,
response_deserializer=core__pb2.FileEvent.FromString,
)
self.AddNode = channel.unary_unary(
'/core.CoreApi/AddNode',
request_serializer=core__pb2.AddNodeRequest.SerializeToString,
response_deserializer=core__pb2.AddNodeResponse.FromString,
)
self.GetNode = channel.unary_unary(
'/core.CoreApi/GetNode',
request_serializer=core__pb2.GetNodeRequest.SerializeToString,
response_deserializer=core__pb2.GetNodeResponse.FromString,
)
self.EditNode = channel.unary_unary(
'/core.CoreApi/EditNode',
request_serializer=core__pb2.EditNodeRequest.SerializeToString,
response_deserializer=core__pb2.EditNodeResponse.FromString,
)
self.DeleteNode = channel.unary_unary(
'/core.CoreApi/DeleteNode',
request_serializer=core__pb2.DeleteNodeRequest.SerializeToString,
response_deserializer=core__pb2.DeleteNodeResponse.FromString,
)
self.GetNodeLinks = channel.unary_unary(
'/core.CoreApi/GetNodeLinks',
request_serializer=core__pb2.GetNodeLinksRequest.SerializeToString,
response_deserializer=core__pb2.GetNodeLinksResponse.FromString,
)
self.AddLink = channel.unary_unary(
'/core.CoreApi/AddLink',
request_serializer=core__pb2.AddLinkRequest.SerializeToString,
response_deserializer=core__pb2.AddLinkResponse.FromString,
)
self.EditLink = channel.unary_unary(
'/core.CoreApi/EditLink',
request_serializer=core__pb2.EditLinkRequest.SerializeToString,
response_deserializer=core__pb2.EditLinkResponse.FromString,
)
self.DeleteLink = channel.unary_unary(
'/core.CoreApi/DeleteLink',
request_serializer=core__pb2.DeleteLinkRequest.SerializeToString,
response_deserializer=core__pb2.DeleteLinkResponse.FromString,
)
self.GetHooks = channel.unary_unary(
'/core.CoreApi/GetHooks',
request_serializer=core__pb2.GetHooksRequest.SerializeToString,
response_deserializer=core__pb2.GetHooksResponse.FromString,
)
self.AddHook = channel.unary_unary(
'/core.CoreApi/AddHook',
request_serializer=core__pb2.AddHookRequest.SerializeToString,
response_deserializer=core__pb2.AddHookResponse.FromString,
)
self.GetMobilityConfigs = channel.unary_unary(
'/core.CoreApi/GetMobilityConfigs',
request_serializer=core__pb2.GetMobilityConfigsRequest.SerializeToString,
response_deserializer=core__pb2.GetMobilityConfigsResponse.FromString,
)
self.GetMobilityConfig = channel.unary_unary(
'/core.CoreApi/GetMobilityConfig',
request_serializer=core__pb2.GetMobilityConfigRequest.SerializeToString,
response_deserializer=core__pb2.GetMobilityConfigResponse.FromString,
)
self.SetMobilityConfig = channel.unary_unary(
'/core.CoreApi/SetMobilityConfig',
request_serializer=core__pb2.SetMobilityConfigRequest.SerializeToString,
response_deserializer=core__pb2.SetMobilityConfigResponse.FromString,
)
self.MobilityAction = channel.unary_unary(
'/core.CoreApi/MobilityAction',
request_serializer=core__pb2.MobilityActionRequest.SerializeToString,
response_deserializer=core__pb2.MobilityActionResponse.FromString,
)
self.GetServices = channel.unary_unary(
'/core.CoreApi/GetServices',
request_serializer=core__pb2.GetServicesRequest.SerializeToString,
response_deserializer=core__pb2.GetServicesResponse.FromString,
)
self.GetServiceDefaults = channel.unary_unary(
'/core.CoreApi/GetServiceDefaults',
request_serializer=core__pb2.GetServiceDefaultsRequest.SerializeToString,
response_deserializer=core__pb2.GetServiceDefaultsResponse.FromString,
)
self.SetServiceDefaults = channel.unary_unary(
'/core.CoreApi/SetServiceDefaults',
request_serializer=core__pb2.SetServiceDefaultsRequest.SerializeToString,
response_deserializer=core__pb2.SetServiceDefaultsResponse.FromString,
)
self.GetNodeService = channel.unary_unary(
'/core.CoreApi/GetNodeService',
request_serializer=core__pb2.GetNodeServiceRequest.SerializeToString,
response_deserializer=core__pb2.GetNodeServiceResponse.FromString,
)
self.GetNodeServiceFile = channel.unary_unary(
'/core.CoreApi/GetNodeServiceFile',
request_serializer=core__pb2.GetNodeServiceFileRequest.SerializeToString,
response_deserializer=core__pb2.GetNodeServiceFileResponse.FromString,
)
self.SetNodeService = channel.unary_unary(
'/core.CoreApi/SetNodeService',
request_serializer=core__pb2.SetNodeServiceRequest.SerializeToString,
response_deserializer=core__pb2.SetNodeServiceResponse.FromString,
)
self.SetNodeServiceFile = channel.unary_unary(
'/core.CoreApi/SetNodeServiceFile',
request_serializer=core__pb2.SetNodeServiceFileRequest.SerializeToString,
response_deserializer=core__pb2.SetNodeServiceFileResponse.FromString,
)
self.ServiceAction = channel.unary_unary(
'/core.CoreApi/ServiceAction',
request_serializer=core__pb2.ServiceActionRequest.SerializeToString,
response_deserializer=core__pb2.ServiceActionResponse.FromString,
)
self.GetWlanConfig = channel.unary_unary(
'/core.CoreApi/GetWlanConfig',
request_serializer=core__pb2.GetWlanConfigRequest.SerializeToString,
response_deserializer=core__pb2.GetWlanConfigResponse.FromString,
)
self.SetWlanConfig = channel.unary_unary(
'/core.CoreApi/SetWlanConfig',
request_serializer=core__pb2.SetWlanConfigRequest.SerializeToString,
response_deserializer=core__pb2.SetWlanConfigResponse.FromString,
)
self.GetEmaneConfig = channel.unary_unary(
'/core.CoreApi/GetEmaneConfig',
request_serializer=core__pb2.GetEmaneConfigRequest.SerializeToString,
response_deserializer=core__pb2.GetEmaneConfigResponse.FromString,
)
self.SetEmaneConfig = channel.unary_unary(
'/core.CoreApi/SetEmaneConfig',
request_serializer=core__pb2.SetEmaneConfigRequest.SerializeToString,
response_deserializer=core__pb2.SetEmaneConfigResponse.FromString,
)
self.GetEmaneModels = channel.unary_unary(
'/core.CoreApi/GetEmaneModels',
request_serializer=core__pb2.GetEmaneModelsRequest.SerializeToString,
response_deserializer=core__pb2.GetEmaneModelsResponse.FromString,
)
self.GetEmaneModelConfig = channel.unary_unary(
'/core.CoreApi/GetEmaneModelConfig',
request_serializer=core__pb2.GetEmaneModelConfigRequest.SerializeToString,
response_deserializer=core__pb2.GetEmaneModelConfigResponse.FromString,
)
self.SetEmaneModelConfig = channel.unary_unary(
'/core.CoreApi/SetEmaneModelConfig',
request_serializer=core__pb2.SetEmaneModelConfigRequest.SerializeToString,
response_deserializer=core__pb2.SetEmaneModelConfigResponse.FromString,
)
self.GetEmaneModelConfigs = channel.unary_unary(
'/core.CoreApi/GetEmaneModelConfigs',
request_serializer=core__pb2.GetEmaneModelConfigsRequest.SerializeToString,
response_deserializer=core__pb2.GetEmaneModelConfigsResponse.FromString,
)
self.SaveXml = channel.unary_unary(
'/core.CoreApi/SaveXml',
request_serializer=core__pb2.SaveXmlRequest.SerializeToString,
response_deserializer=core__pb2.SaveXmlResponse.FromString,
)
self.OpenXml = channel.unary_unary(
'/core.CoreApi/OpenXml',
request_serializer=core__pb2.OpenXmlRequest.SerializeToString,
response_deserializer=core__pb2.OpenXmlResponse.FromString,
)
class CoreApiServicer(object):
# missing associated documentation comment in .proto file
pass
def CreateSession(self, request, context):
"""session rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteSession(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetSessions(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetSession(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetSessionOptions(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetSessionOptions(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetSessionLocation(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetSessionLocation(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetSessionState(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def NodeEvents(self, request, context):
"""event streams
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def LinkEvents(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SessionEvents(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ConfigEvents(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ExceptionEvents(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def FileEvents(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def AddNode(self, request, context):
"""node rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetNode(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def EditNode(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteNode(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetNodeLinks(self, request, context):
"""link rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def AddLink(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def EditLink(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def DeleteLink(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetHooks(self, request, context):
"""hook rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def AddHook(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetMobilityConfigs(self, request, context):
"""mobility rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetMobilityConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetMobilityConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def MobilityAction(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetServices(self, request, context):
"""service rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetServiceDefaults(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetServiceDefaults(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetNodeService(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetNodeServiceFile(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetNodeService(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetNodeServiceFile(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ServiceAction(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetWlanConfig(self, request, context):
"""wlan rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetWlanConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetEmaneConfig(self, request, context):
"""emane rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetEmaneConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetEmaneModels(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetEmaneModelConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetEmaneModelConfig(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetEmaneModelConfigs(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SaveXml(self, request, context):
"""xml rpc
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def OpenXml(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CoreApiServicer_to_server(servicer, server):
rpc_method_handlers = {
'CreateSession': grpc.unary_unary_rpc_method_handler(
servicer.CreateSession,
request_deserializer=core__pb2.CreateSessionRequest.FromString,
response_serializer=core__pb2.CreateSessionResponse.SerializeToString,
),
'DeleteSession': grpc.unary_unary_rpc_method_handler(
servicer.DeleteSession,
request_deserializer=core__pb2.DeleteSessionRequest.FromString,
response_serializer=core__pb2.DeleteSessionResponse.SerializeToString,
),
'GetSessions': grpc.unary_unary_rpc_method_handler(
servicer.GetSessions,
request_deserializer=core__pb2.GetSessionsRequest.FromString,
response_serializer=core__pb2.GetSessionsResponse.SerializeToString,
),
'GetSession': grpc.unary_unary_rpc_method_handler(
servicer.GetSession,
request_deserializer=core__pb2.GetSessionRequest.FromString,
response_serializer=core__pb2.GetSessionResponse.SerializeToString,
),
'GetSessionOptions': grpc.unary_unary_rpc_method_handler(
servicer.GetSessionOptions,
request_deserializer=core__pb2.GetSessionOptionsRequest.FromString,
response_serializer=core__pb2.GetSessionOptionsResponse.SerializeToString,
),
'SetSessionOptions': grpc.unary_unary_rpc_method_handler(
servicer.SetSessionOptions,
request_deserializer=core__pb2.SetSessionOptionsRequest.FromString,
response_serializer=core__pb2.SetSessionOptionsResponse.SerializeToString,
),
'GetSessionLocation': grpc.unary_unary_rpc_method_handler(
servicer.GetSessionLocation,
request_deserializer=core__pb2.GetSessionLocationRequest.FromString,
response_serializer=core__pb2.GetSessionLocationResponse.SerializeToString,
),
'SetSessionLocation': grpc.unary_unary_rpc_method_handler(
servicer.SetSessionLocation,
request_deserializer=core__pb2.SetSessionLocationRequest.FromString,
response_serializer=core__pb2.SetSessionLocationResponse.SerializeToString,
),
'SetSessionState': grpc.unary_unary_rpc_method_handler(
servicer.SetSessionState,
request_deserializer=core__pb2.SetSessionStateRequest.FromString,
response_serializer=core__pb2.SetSessionStateResponse.SerializeToString,
),
'NodeEvents': grpc.unary_stream_rpc_method_handler(
servicer.NodeEvents,
request_deserializer=core__pb2.NodeEventsRequest.FromString,
response_serializer=core__pb2.NodeEvent.SerializeToString,
),
'LinkEvents': grpc.unary_stream_rpc_method_handler(
servicer.LinkEvents,
request_deserializer=core__pb2.LinkEventsRequest.FromString,
response_serializer=core__pb2.LinkEvent.SerializeToString,
),
'SessionEvents': grpc.unary_stream_rpc_method_handler(
servicer.SessionEvents,
request_deserializer=core__pb2.SessionEventsRequest.FromString,
response_serializer=core__pb2.SessionEvent.SerializeToString,
),
'ConfigEvents': grpc.unary_stream_rpc_method_handler(
servicer.ConfigEvents,
request_deserializer=core__pb2.ConfigEventsRequest.FromString,
response_serializer=core__pb2.ConfigEvent.SerializeToString,
),
'ExceptionEvents': grpc.unary_stream_rpc_method_handler(
servicer.ExceptionEvents,
request_deserializer=core__pb2.ExceptionEventsRequest.FromString,
response_serializer=core__pb2.ExceptionEvent.SerializeToString,
),
'FileEvents': grpc.unary_stream_rpc_method_handler(
servicer.FileEvents,
request_deserializer=core__pb2.FileEventsRequest.FromString,
response_serializer=core__pb2.FileEvent.SerializeToString,
),
'AddNode': grpc.unary_unary_rpc_method_handler(
servicer.AddNode,
request_deserializer=core__pb2.AddNodeRequest.FromString,
response_serializer=core__pb2.AddNodeResponse.SerializeToString,
),
'GetNode': grpc.unary_unary_rpc_method_handler(
servicer.GetNode,
request_deserializer=core__pb2.GetNodeRequest.FromString,
response_serializer=core__pb2.GetNodeResponse.SerializeToString,
),
'EditNode': grpc.unary_unary_rpc_method_handler(
servicer.EditNode,
request_deserializer=core__pb2.EditNodeRequest.FromString,
response_serializer=core__pb2.EditNodeResponse.SerializeToString,
),
'DeleteNode': grpc.unary_unary_rpc_method_handler(
servicer.DeleteNode,
request_deserializer=core__pb2.DeleteNodeRequest.FromString,
response_serializer=core__pb2.DeleteNodeResponse.SerializeToString,
),
'GetNodeLinks': grpc.unary_unary_rpc_method_handler(
servicer.GetNodeLinks,
request_deserializer=core__pb2.GetNodeLinksRequest.FromString,
response_serializer=core__pb2.GetNodeLinksResponse.SerializeToString,
),
'AddLink': grpc.unary_unary_rpc_method_handler(
servicer.AddLink,
request_deserializer=core__pb2.AddLinkRequest.FromString,
response_serializer=core__pb2.AddLinkResponse.SerializeToString,
),
'EditLink': grpc.unary_unary_rpc_method_handler(
servicer.EditLink,
request_deserializer=core__pb2.EditLinkRequest.FromString,
response_serializer=core__pb2.EditLinkResponse.SerializeToString,
),
'DeleteLink': grpc.unary_unary_rpc_method_handler(
servicer.DeleteLink,
request_deserializer=core__pb2.DeleteLinkRequest.FromString,
response_serializer=core__pb2.DeleteLinkResponse.SerializeToString,
),
'GetHooks': grpc.unary_unary_rpc_method_handler(
servicer.GetHooks,
request_deserializer=core__pb2.GetHooksRequest.FromString,
response_serializer=core__pb2.GetHooksResponse.SerializeToString,
),
'AddHook': grpc.unary_unary_rpc_method_handler(
servicer.AddHook,
request_deserializer=core__pb2.AddHookRequest.FromString,
response_serializer=core__pb2.AddHookResponse.SerializeToString,
),
'GetMobilityConfigs': grpc.unary_unary_rpc_method_handler(
servicer.GetMobilityConfigs,
request_deserializer=core__pb2.GetMobilityConfigsRequest.FromString,
response_serializer=core__pb2.GetMobilityConfigsResponse.SerializeToString,
),
'GetMobilityConfig': grpc.unary_unary_rpc_method_handler(
servicer.GetMobilityConfig,
request_deserializer=core__pb2.GetMobilityConfigRequest.FromString,
response_serializer=core__pb2.GetMobilityConfigResponse.SerializeToString,
),
'SetMobilityConfig': grpc.unary_unary_rpc_method_handler(
servicer.SetMobilityConfig,
request_deserializer=core__pb2.SetMobilityConfigRequest.FromString,
response_serializer=core__pb2.SetMobilityConfigResponse.SerializeToString,
),
'MobilityAction': grpc.unary_unary_rpc_method_handler(
servicer.MobilityAction,
request_deserializer=core__pb2.MobilityActionRequest.FromString,
response_serializer=core__pb2.MobilityActionResponse.SerializeToString,
),
'GetServices': grpc.unary_unary_rpc_method_handler(
servicer.GetServices,
request_deserializer=core__pb2.GetServicesRequest.FromString,
response_serializer=core__pb2.GetServicesResponse.SerializeToString,
),
'GetServiceDefaults': grpc.unary_unary_rpc_method_handler(
servicer.GetServiceDefaults,
request_deserializer=core__pb2.GetServiceDefaultsRequest.FromString,
response_serializer=core__pb2.GetServiceDefaultsResponse.SerializeToString,
),
'SetServiceDefaults': grpc.unary_unary_rpc_method_handler(
servicer.SetServiceDefaults,
request_deserializer=core__pb2.SetServiceDefaultsRequest.FromString,
response_serializer=core__pb2.SetServiceDefaultsResponse.SerializeToString,
),
'GetNodeService': grpc.unary_unary_rpc_method_handler(
servicer.GetNodeService,
request_deserializer=core__pb2.GetNodeServiceRequest.FromString,
response_serializer=core__pb2.GetNodeServiceResponse.SerializeToString,
),
'GetNodeServiceFile': grpc.unary_unary_rpc_method_handler(
servicer.GetNodeServiceFile,
request_deserializer=core__pb2.GetNodeServiceFileRequest.FromString,
response_serializer=core__pb2.GetNodeServiceFileResponse.SerializeToString,
),
'SetNodeService': grpc.unary_unary_rpc_method_handler(
servicer.SetNodeService,
request_deserializer=core__pb2.SetNodeServiceRequest.FromString,
response_serializer=core__pb2.SetNodeServiceResponse.SerializeToString,
),
'SetNodeServiceFile': grpc.unary_unary_rpc_method_handler(
servicer.SetNodeServiceFile,
request_deserializer=core__pb2.SetNodeServiceFileRequest.FromString,
response_serializer=core__pb2.SetNodeServiceFileResponse.SerializeToString,
),
'ServiceAction': grpc.unary_unary_rpc_method_handler(
servicer.ServiceAction,
request_deserializer=core__pb2.ServiceActionRequest.FromString,
response_serializer=core__pb2.ServiceActionResponse.SerializeToString,
),
'GetWlanConfig': grpc.unary_unary_rpc_method_handler(
servicer.GetWlanConfig,
request_deserializer=core__pb2.GetWlanConfigRequest.FromString,
response_serializer=core__pb2.GetWlanConfigResponse.SerializeToString,
),
'SetWlanConfig': grpc.unary_unary_rpc_method_handler(
servicer.SetWlanConfig,
request_deserializer=core__pb2.SetWlanConfigRequest.FromString,
response_serializer=core__pb2.SetWlanConfigResponse.SerializeToString,
),
'GetEmaneConfig': grpc.unary_unary_rpc_method_handler(
servicer.GetEmaneConfig,
request_deserializer=core__pb2.GetEmaneConfigRequest.FromString,
response_serializer=core__pb2.GetEmaneConfigResponse.SerializeToString,
),
'SetEmaneConfig': grpc.unary_unary_rpc_method_handler(
servicer.SetEmaneConfig,
request_deserializer=core__pb2.SetEmaneConfigRequest.FromString,
response_serializer=core__pb2.SetEmaneConfigResponse.SerializeToString,
),
'GetEmaneModels': grpc.unary_unary_rpc_method_handler(
servicer.GetEmaneModels,
request_deserializer=core__pb2.GetEmaneModelsRequest.FromString,
response_serializer=core__pb2.GetEmaneModelsResponse.SerializeToString,
),
'GetEmaneModelConfig': grpc.unary_unary_rpc_method_handler(
servicer.GetEmaneModelConfig,
request_deserializer=core__pb2.GetEmaneModelConfigRequest.FromString,
response_serializer=core__pb2.GetEmaneModelConfigResponse.SerializeToString,
),
'SetEmaneModelConfig': grpc.unary_unary_rpc_method_handler(
servicer.SetEmaneModelConfig,
request_deserializer=core__pb2.SetEmaneModelConfigRequest.FromString,
response_serializer=core__pb2.SetEmaneModelConfigResponse.SerializeToString,
),
'GetEmaneModelConfigs': grpc.unary_unary_rpc_method_handler(
servicer.GetEmaneModelConfigs,
request_deserializer=core__pb2.GetEmaneModelConfigsRequest.FromString,
response_serializer=core__pb2.GetEmaneModelConfigsResponse.SerializeToString,
),
'SaveXml': grpc.unary_unary_rpc_method_handler(
servicer.SaveXml,
request_deserializer=core__pb2.SaveXmlRequest.FromString,
response_serializer=core__pb2.SaveXmlResponse.SerializeToString,
),
'OpenXml': grpc.unary_unary_rpc_method_handler(
servicer.OpenXml,
request_deserializer=core__pb2.OpenXmlRequest.FromString,
response_serializer=core__pb2.OpenXmlResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'core.CoreApi', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))

View file

@ -9,13 +9,13 @@ import grpc
from concurrent import futures from concurrent import futures
from core.emulator.emudata import NodeOptions, InterfaceData, LinkOptions from core.emulator.emudata import NodeOptions, InterfaceData, LinkOptions
from core.enumerations import NodeTypes, EventTypes, LinkTypes from core.emulator.enumerations import NodeTypes, EventTypes, LinkTypes
from core.grpc import core_pb2 from core.api.grpc import core_pb2
from core.grpc import core_pb2_grpc from core.api.grpc import core_pb2_grpc
from core.misc import nodeutils from core.nodes import nodeutils
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.mobility import BasicRangeModel, Ns2ScriptedMobility from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.service import ServiceManager from core.services.coreservices import ServiceManager
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 _ONE_DAY_IN_SECONDS = 60 * 60 * 24
@ -68,7 +68,7 @@ def get_emane_model_id(_id, interface):
def convert_link(session, link_data): def convert_link(session, link_data):
interface_one = None interface_one = None
if link_data.interface1_id is not None: if link_data.interface1_id is not None:
node = session.get_object(link_data.node1_id) node = session.get_node(link_data.node1_id)
interface = node.netif(link_data.interface1_id) interface = node.netif(link_data.interface1_id)
interface_one = core_pb2.Interface( interface_one = core_pb2.Interface(
id=link_data.interface1_id, name=interface.name, mac=convert_value(link_data.interface1_mac), id=link_data.interface1_id, name=interface.name, mac=convert_value(link_data.interface1_mac),
@ -77,7 +77,7 @@ def convert_link(session, link_data):
interface_two = None interface_two = None
if link_data.interface2_id is not None: if link_data.interface2_id is not None:
node = session.get_object(link_data.node2_id) node = session.get_node(link_data.node2_id)
interface = node.netif(link_data.interface2_id) interface = node.netif(link_data.interface2_id)
interface_two = core_pb2.Interface( interface_two = core_pb2.Interface(
id=link_data.interface2_id, name=interface.name, mac=convert_value(link_data.interface2_mac), id=link_data.interface2_id, name=interface.name, mac=convert_value(link_data.interface2_mac),
@ -143,7 +143,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
def get_node(self, session, _id, context): def get_node(self, session, _id, context):
try: try:
return session.get_object(_id) return session.get_node(_id)
except KeyError: except KeyError:
context.abort(grpc.StatusCode.NOT_FOUND, "node {} not found".format(_id)) context.abort(grpc.StatusCode.NOT_FOUND, "node {} not found".format(_id))
@ -233,8 +233,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
links = [] links = []
nodes = [] nodes = []
for node_id in session.objects: for _id in session.nodes:
node = session.objects[node_id] node = session.nodes[_id]
if not isinstance(node.id, int): if not isinstance(node.id, int):
continue continue

View file

@ -10,27 +10,26 @@ import select
import socket import socket
import threading import threading
from core.api import coreapi from core.api.tlv import coreapi
from core.coreobj import PyCoreNet from core.nodes.base import CoreNodeBase, CoreNetworkBase
from core.coreobj import PyCoreNode from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigFlags
from core.enumerations import ConfigFlags from core.emulator.enumerations import ConfigTlvs
from core.enumerations import ConfigTlvs from core.emulator.enumerations import EventTlvs
from core.enumerations import EventTlvs from core.emulator.enumerations import EventTypes
from core.enumerations import EventTypes from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import FileTlvs
from core.enumerations import FileTlvs from core.emulator.enumerations import LinkTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageTypes
from core.enumerations import MessageTypes from core.emulator.enumerations import NodeTlvs
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import RegisterTlvs
from core.enumerations import RegisterTlvs from core.nodes import nodeutils
from core.misc import nodeutils from core.nodes.ipaddress import IpAddress
from core.misc.ipaddress import IpAddress from core.nodes.interface import GreTap
from core.netns.vif import GreTap from core.nodes.network import GreTapBridge
from core.netns.vnet import GreTapBridge from core.nodes.physical import PhysicalNode
from core.phys.pnodes import PhysicalNode
class CoreDistributedServer(object): class CoreDistributedServer(object):
@ -420,7 +419,7 @@ class CoreBroker(object):
gt = GreTap(node=None, name=None, session=self.session, gt = GreTap(node=None, name=None, session=self.session,
remoteip=remoteip, key=key) remoteip=remoteip, key=key)
else: else:
gt = self.session.add_object(cls=GreTapBridge, _id=_id, policy="ACCEPT", remoteip=remoteip, key=key) gt = self.session.create_node(cls=GreTapBridge, _id=_id, policy="ACCEPT", remoteip=remoteip, key=key)
gt.localnum = localnum gt.localnum = localnum
gt.remotenum = remotenum gt.remotenum = remotenum
self.tunnels[key] = gt self.tunnels[key] = gt
@ -443,7 +442,7 @@ class CoreBroker(object):
:rtype: list :rtype: list
""" """
try: try:
net = self.session.get_object(node_id) net = self.session.get_node(node_id)
logging.info("adding net tunnel for: id(%s) %s", node_id, net) logging.info("adding net tunnel for: id(%s) %s", node_id, net)
except KeyError: except KeyError:
raise KeyError("network node %s not found" % node_id) raise KeyError("network node %s not found" % node_id)
@ -517,7 +516,7 @@ class CoreBroker(object):
except KeyError: except KeyError:
gt = None gt = None
if gt: if gt:
self.session.delete_object(gt.id) self.session.delete_node(gt.id)
del gt del gt
def gettunnel(self, n1num, n2num): def gettunnel(self, n1num, n2num):
@ -757,7 +756,7 @@ class CoreBroker(object):
if nodecls is None: if nodecls is None:
logging.warn("broker unimplemented node type %s", nodetype) logging.warn("broker unimplemented node type %s", nodetype)
return handle_locally, servers return handle_locally, servers
if issubclass(nodecls, PyCoreNet) and nodetype != NodeTypes.WIRELESS_LAN.value: if issubclass(nodecls, CoreNetworkBase) and nodetype != NodeTypes.WIRELESS_LAN.value:
# network node replicated on all servers; could be optimized # network node replicated on all servers; could be optimized
# don"t replicate WLANs, because ebtables rules won"t work # don"t replicate WLANs, because ebtables rules won"t work
servers = self.getservers() servers = self.getservers()
@ -768,7 +767,7 @@ class CoreBroker(object):
# do not record server name for networks since network # do not record server name for networks since network
# nodes are replicated across all server # nodes are replicated across all server
return handle_locally, servers return handle_locally, servers
elif issubclass(nodecls, PyCoreNode): elif issubclass(nodecls, CoreNodeBase):
name = message.get_tlv(NodeTlvs.NAME.value) name = message.get_tlv(NodeTlvs.NAME.value)
if name: if name:
serverfiletxt = "%s %s %s" % (n, name, nodecls) serverfiletxt = "%s %s %s" % (n, name, nodecls)

View file

@ -10,22 +10,22 @@ import struct
from enum import Enum from enum import Enum
from core.enumerations import ConfigTlvs from core.emulator.enumerations import ConfigTlvs
from core.enumerations import EventTlvs from core.emulator.enumerations import EventTlvs
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import ExceptionTlvs from core.emulator.enumerations import ExceptionTlvs
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import FileTlvs from core.emulator.enumerations import FileTlvs
from core.enumerations import InterfaceTlvs from core.emulator.enumerations import InterfaceTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import LinkTlvs
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTlvs
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.enumerations import SessionTlvs from core.emulator.enumerations import SessionTlvs
from core.misc import structutils from core.api.tlv import structutils
from core.misc.ipaddress import IpAddress from core.nodes.ipaddress import IpAddress
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
class CoreTlvData(object): class CoreTlvData(object):

View file

@ -13,36 +13,34 @@ import threading
import time import time
from itertools import repeat from itertools import repeat
from core.api import coreapi from core.api.tlv import coreapi, dataconversion, structutils
from core.api import dataconversion from core.config import ConfigShim
from core.conf import ConfigShim from core.emulator.data import ConfigData, ExceptionData
from core.data import ConfigData, ExceptionData from core.emulator.data import EventData
from core.data import EventData from core.emulator.data import FileData
from core.data import FileData
from core.emulator.emudata import InterfaceData from core.emulator.emudata import InterfaceData
from core.emulator.emudata import LinkOptions from core.emulator.emudata import LinkOptions
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import ConfigFlags from core.emulator.enumerations import ConfigFlags
from core.enumerations import ConfigTlvs from core.emulator.enumerations import ConfigTlvs
from core.enumerations import EventTlvs from core.emulator.enumerations import EventTlvs
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import ExceptionTlvs from core.emulator.enumerations import ExceptionTlvs
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import FileTlvs from core.emulator.enumerations import FileTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import LinkTlvs
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTlvs
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.enumerations import SessionTlvs from core.emulator.enumerations import SessionTlvs
from core.misc import nodeutils from core.nodes import nodeutils
from core.misc import structutils from core import utils
from core.misc import utils from core.services.coreservices import ServiceManager
from core.service import ServiceManager from core.services.coreservices import ServiceShim
from core.service import ServiceShim
class CoreHandler(SocketServer.BaseRequestHandler): class CoreHandler(SocketServer.BaseRequestHandler):
@ -774,7 +772,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
return () return ()
try: try:
node = self.session.get_object(node_num) node = self.session.get_node(node_num)
# build common TLV items for reply # build common TLV items for reply
tlv_data = "" tlv_data = ""
@ -1135,7 +1133,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
if not node_id: if not node_id:
return replies return replies
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
if node is None: if node is None:
logging.warn("request to configure service for unknown node %s", node_id) logging.warn("request to configure service for unknown node %s", node_id)
return replies return replies
@ -1418,7 +1416,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
if event_type.value <= EventTypes.SHUTDOWN_STATE.value: if event_type.value <= EventTypes.SHUTDOWN_STATE.value:
if node_id is not None: if node_id is not None:
try: try:
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
except KeyError: except KeyError:
raise KeyError("Event message for unknown node %d" % node_id) raise KeyError("Event message for unknown node %d" % node_id)
@ -1442,7 +1440,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
self.session.instantiate() self.session.instantiate()
# after booting nodes attempt to send emulation id for nodes waiting on status # after booting nodes attempt to send emulation id for nodes waiting on status
for _id in self.session.objects: for _id in self.session.nodes:
self.send_node_emulation_id(_id) self.send_node_emulation_id(_id)
elif event_type == EventTypes.RUNTIME_STATE: elif event_type == EventTypes.RUNTIME_STATE:
if self.session.master: if self.session.master:
@ -1508,7 +1506,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
name = event_data.name name = event_data.name
try: try:
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
except KeyError: except KeyError:
logging.warn("ignoring event for service '%s', unknown node '%s'", name, node_id) logging.warn("ignoring event for service '%s', unknown node '%s'", name, node_id)
return return
@ -1679,13 +1677,13 @@ class CoreHandler(SocketServer.BaseRequestHandler):
nodes_data = [] nodes_data = []
links_data = [] links_data = []
with self.session._objects_lock: with self.session._nodes_lock:
for obj in self.session.objects.itervalues(): for node in self.session.nodes.itervalues():
node_data = obj.data(message_type=MessageFlags.ADD.value) node_data = node.data(message_type=MessageFlags.ADD.value)
if node_data: if node_data:
nodes_data.append(node_data) nodes_data.append(node_data)
node_links = obj.all_link_data(flags=MessageFlags.ADD.value) node_links = node.all_link_data(flags=MessageFlags.ADD.value)
for link_data in node_links: for link_data in node_links:
links_data.append(link_data) links_data.append(link_data)
@ -1717,7 +1715,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
for node_id, service in service_configs: for node_id, service in service_configs:
opaque = "service:%s" % service.name opaque = "service:%s" % service.name
data_types = tuple(repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys))) data_types = tuple(repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys)))
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
values = ServiceShim.tovaluelist(node, service) values = ServiceShim.tovaluelist(node, service)
config_data = ConfigData( config_data = ConfigData(
message_type=0, message_type=0,

View file

@ -2,10 +2,9 @@
Converts CORE data objects into legacy API messages. Converts CORE data objects into legacy API messages.
""" """
from core.api import coreapi from core.api.tlv import coreapi, structutils
from core.enumerations import ConfigTlvs from core.emulator.enumerations import ConfigTlvs
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTlvs
from core.misc import structutils
def convert_node(node_data): def convert_node(node_data):

View file

@ -5,7 +5,7 @@ Common support for configurable CORE objects.
import logging import logging
from collections import OrderedDict from collections import OrderedDict
from core.data import ConfigData from core.emulator.data import ConfigData
class ConfigShim(object): class ConfigShim(object):

View file

@ -1,758 +0,0 @@
"""
Defines the basic objects for CORE emulation: the PyCoreObj base class, along with PyCoreNode,
PyCoreNet, and PyCoreNetIf.
"""
import os
import shutil
import socket
import threading
from socket import AF_INET
from socket import AF_INET6
from core.data import NodeData, LinkData
from core.enumerations import LinkTypes
from core.misc import ipaddress
class Position(object):
"""
Helper class for Cartesian coordinate position
"""
def __init__(self, x=None, y=None, z=None):
"""
Creates a Position instance.
:param x: x position
:param y: y position
:param z: z position
:return:
"""
self.x = x
self.y = y
self.z = z
def set(self, x=None, y=None, z=None):
"""
Returns True if the position has actually changed.
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
if self.x == x and self.y == y and self.z == z:
return False
self.x = x
self.y = y
self.z = z
return True
def get(self):
"""
Retrieve x,y,z position.
:return: x,y,z position tuple
:rtype: tuple
"""
return self.x, self.y, self.z
class PyCoreObj(object):
"""
Base class for CORE objects (nodes and networks)
"""
apitype = None
# TODO: appears start has no usage, verify and remove
def __init__(self, session, _id=None, name=None, start=True):
"""
Creates a PyCoreObj instance.
:param core.session.Session session: CORE session object
:param int _id: id
:param str name: object name
:param bool start: start value
:return:
"""
self.session = session
if _id is None:
_id = session.get_node_id()
self.id = _id
if name is None:
name = "o%s" % self.id
self.name = name
self.type = None
self.server = None
self.services = None
# ifindex is key, PyCoreNetIf instance is value
self._netif = {}
self.ifindex = 0
self.canvas = None
self.icon = None
self.opaque = None
self.position = Position()
def startup(self):
"""
Each object implements its own startup method.
:return: nothing
"""
raise NotImplementedError
def shutdown(self):
"""
Each object implements its own shutdown method.
:return: nothing
"""
raise NotImplementedError
def setposition(self, x=None, y=None, z=None):
"""
Set the (x,y,z) position of the object.
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
return self.position.set(x=x, y=y, z=z)
def getposition(self):
"""
Return an (x,y,z) tuple representing this object's position.
:return: x,y,z position tuple
:rtype: tuple
"""
return self.position.get()
def ifname(self, ifindex):
"""
Retrieve interface name for index.
:param int ifindex: interface index
:return: interface name
:rtype: str
"""
return self._netif[ifindex].name
def netifs(self, sort=False):
"""
Retrieve network interfaces, sorted if desired.
:param bool sort: boolean used to determine if interfaces should be sorted
:return: network interfaces
:rtype: list
"""
if sort:
return map(lambda k: self._netif[k], sorted(self._netif.keys()))
else:
return self._netif.itervalues()
def numnetif(self):
"""
Return the attached interface count.
:return: number of network interfaces
:rtype: int
"""
return len(self._netif)
def getifindex(self, netif):
"""
Retrieve index for an interface.
:param PyCoreNetIf netif: interface to get index for
:return: interface index if found, -1 otherwise
:rtype: int
"""
for ifindex in self._netif:
if self._netif[ifindex] is netif:
return ifindex
return -1
def newifindex(self):
"""
Create a new interface index.
:return: interface index
:rtype: int
"""
while self.ifindex in self._netif:
self.ifindex += 1
ifindex = self.ifindex
self.ifindex += 1
return ifindex
def data(self, message_type, lat=None, lon=None, alt=None):
"""
Build a data object for this node.
:param message_type: purpose for the data object we are creating
:param str lat: latitude
:param str lon: longitude
:param str alt: altitude
:return: node data object
:rtype: core.data.NodeData
"""
if self.apitype is None:
return None
x, y, _ = self.getposition()
model = self.type
emulation_server = self.server
services = self.services
if services is not None:
services = "|".join([service.name for service in services])
node_data = NodeData(
message_type=message_type,
id=self.id,
node_type=self.apitype,
name=self.name,
emulation_id=self.id,
canvas=self.canvas,
icon=self.icon,
opaque=self.opaque,
x_position=x,
y_position=y,
latitude=lat,
longitude=lon,
altitude=alt,
model=model,
emulation_server=emulation_server,
services=services
)
return node_data
def all_link_data(self, flags):
"""
Build CORE Link data for this object. There is no default
method for PyCoreObjs as PyCoreNodes do not implement this but
PyCoreNets do.
:param flags: message flags
:return: list of link data
:rtype: core.data.LinkData
"""
return []
class PyCoreNode(PyCoreObj):
"""
Base class for CORE nodes.
"""
def __init__(self, session, _id=None, name=None, start=True):
"""
Create a PyCoreNode instance.
:param core.session.Session session: CORE session object
:param int _id: object id
:param str name: object name
:param bool start: boolean for starting
"""
super(PyCoreNode, self).__init__(session, _id, name, start=start)
self.services = []
self.nodedir = None
self.tmpnodedir = False
def addservice(self, service):
"""
Add a services to the service list.
:param core.service.CoreService service: service to add
:return: nothing
"""
if service is not None:
self.services.append(service)
def makenodedir(self):
"""
Create the node directory.
:return: nothing
"""
if self.nodedir is None:
self.nodedir = os.path.join(self.session.session_dir, self.name + ".conf")
os.makedirs(self.nodedir)
self.tmpnodedir = True
else:
self.tmpnodedir = False
def rmnodedir(self):
"""
Remove the node directory, unless preserve directory has been set.
:return: nothing
"""
preserve = self.session.options.get_config("preservedir") == "1"
if preserve:
return
if self.tmpnodedir:
shutil.rmtree(self.nodedir, ignore_errors=True)
def addnetif(self, netif, ifindex):
"""
Add network interface to node and set the network interface index if successful.
:param PyCoreNetIf netif: network interface to add
:param int ifindex: interface index
:return: nothing
"""
if ifindex in self._netif:
raise ValueError("ifindex %s already exists" % ifindex)
self._netif[ifindex] = netif
# TODO: this should have probably been set ahead, seems bad to me, check for failure and fix
netif.netindex = ifindex
def delnetif(self, ifindex):
"""
Delete a network interface
:param int ifindex: interface index to delete
:return: nothing
"""
if ifindex not in self._netif:
raise ValueError("ifindex %s does not exist" % ifindex)
netif = self._netif.pop(ifindex)
netif.shutdown()
del netif
# TODO: net parameter is not used, remove
def netif(self, ifindex, net=None):
"""
Retrieve network interface.
:param int ifindex: index of interface to retrieve
:param PyCoreNetIf net: network node
:return: network interface, or None if not found
:rtype: PyCoreNetIf
"""
if ifindex in self._netif:
return self._netif[ifindex]
else:
return None
def attachnet(self, ifindex, net):
"""
Attach a network.
:param int ifindex: interface of index to attach
:param PyCoreNetIf net: network to attach
:return:
"""
if ifindex not in self._netif:
raise ValueError("ifindex %s does not exist" % ifindex)
self._netif[ifindex].attachnet(net)
def detachnet(self, ifindex):
"""
Detach network interface.
:param int ifindex: interface index to detach
:return: nothing
"""
if ifindex not in self._netif:
raise ValueError("ifindex %s does not exist" % ifindex)
self._netif[ifindex].detachnet()
def setposition(self, x=None, y=None, z=None):
"""
Set position.
:param x: x position
:param y: y position
:param z: z position
:return: nothing
"""
changed = super(PyCoreNode, self).setposition(x, y, z)
if changed:
for netif in self.netifs(sort=True):
netif.setposition(x, y, z)
def commonnets(self, obj, want_ctrl=False):
"""
Given another node or net object, return common networks between
this node and that object. A list of tuples is returned, with each tuple
consisting of (network, interface1, interface2).
:param obj: object to get common network with
:param want_ctrl: flag set to determine if control network are wanted
:return: tuples of common networks
:rtype: list
"""
common = []
for netif1 in self.netifs():
if not want_ctrl and hasattr(netif1, "control"):
continue
for netif2 in obj.netifs():
if netif1.net == netif2.net:
common.append((netif1.net, netif1, netif2))
return common
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
raise NotImplementedError
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
raise NotImplementedError
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
raise NotImplementedError
def termcmdstring(self, sh):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
raise NotImplementedError
class PyCoreNet(PyCoreObj):
"""
Base class for networks
"""
linktype = LinkTypes.WIRED.value
def __init__(self, session, _id, name, start=True):
"""
Create a PyCoreNet instance.
:param core.session.Session session: CORE session object
:param int _id: object id
:param str name: object name
:param bool start: should object start
"""
super(PyCoreNet, self).__init__(session, _id, name, start=start)
self._linked = {}
self._linked_lock = threading.Lock()
def startup(self):
"""
Each object implements its own startup method.
:return: nothing
"""
raise NotImplementedError
def shutdown(self):
"""
Each object implements its own shutdown method.
:return: nothing
"""
raise NotImplementedError
def attach(self, netif):
"""
Attach network interface.
:param PyCoreNetIf netif: network interface to attach
:return: nothing
"""
i = self.newifindex()
self._netif[i] = netif
netif.netifi = i
with self._linked_lock:
self._linked[netif] = {}
def detach(self, netif):
"""
Detach network interface.
:param PyCoreNetIf netif: network interface to detach
:return: nothing
"""
del self._netif[netif.netifi]
netif.netifi = None
with self._linked_lock:
del self._linked[netif]
def all_link_data(self, flags):
"""
Build link data objects for this network. Each link object describes a link
between this network and a node.
"""
all_links = []
# build a link message from this network node to each node having a
# connected interface
for netif in self.netifs(sort=True):
if not hasattr(netif, "node"):
continue
linked_node = netif.node
uni = False
if linked_node is None:
# two layer-2 switches/hubs linked together via linknet()
if not hasattr(netif, "othernet"):
continue
linked_node = netif.othernet
if linked_node.id == self.id:
continue
netif.swapparams('_params_up')
upstream_params = netif.getparams()
netif.swapparams('_params_up')
if netif.getparams() != upstream_params:
uni = True
unidirectional = 0
if uni:
unidirectional = 1
interface2_ip4 = None
interface2_ip4_mask = None
interface2_ip6 = None
interface2_ip6_mask = None
for address in netif.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = AF_INET
ipl = socket.inet_pton(family, ip)
interface2_ip4 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip4_mask = mask
else:
family = AF_INET6
ipl = socket.inet_pton(family, ip)
interface2_ip6 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip6_mask = mask
link_data = LinkData(
message_type=flags,
node1_id=self.id,
node2_id=linked_node.id,
link_type=self.linktype,
unidirectional=unidirectional,
interface2_id=linked_node.getifindex(netif),
interface2_mac=netif.hwaddr,
interface2_ip4=interface2_ip4,
interface2_ip4_mask=interface2_ip4_mask,
interface2_ip6=interface2_ip6,
interface2_ip6_mask=interface2_ip6_mask,
delay=netif.getparam("delay"),
bandwidth=netif.getparam("bw"),
dup=netif.getparam("duplicate"),
jitter=netif.getparam("jitter"),
per=netif.getparam("loss")
)
all_links.append(link_data)
if not uni:
continue
netif.swapparams('_params_up')
link_data = LinkData(
message_type=0,
node1_id=linked_node.id,
node2_id=self.id,
unidirectional=1,
delay=netif.getparam("delay"),
bandwidth=netif.getparam("bw"),
dup=netif.getparam("duplicate"),
jitter=netif.getparam("jitter"),
per=netif.getparam("loss")
)
netif.swapparams('_params_up')
all_links.append(link_data)
return all_links
class PyCoreNetIf(object):
"""
Base class for network interfaces.
"""
def __init__(self, node, name, mtu):
"""
Creates a PyCoreNetIf instance.
:param core.coreobj.PyCoreNode node: node for interface
:param str name: interface name
:param mtu: mtu value
"""
self.node = node
self.name = name
if not isinstance(mtu, (int, long)):
raise ValueError
self.mtu = mtu
self.net = None
self._params = {}
self.addrlist = []
self.hwaddr = None
# placeholder position hook
self.poshook = lambda a, b, c, d: None
# used with EMANE
self.transport_type = None
# interface index on the network
self.netindex = None
# index used to find flow data
self.flow_id = None
def startup(self):
"""
Startup method for the interface.
:return: nothing
"""
pass
def shutdown(self):
"""
Shutdown method for the interface.
:return: nothing
"""
pass
def attachnet(self, net):
"""
Attach network.
:param core.coreobj.PyCoreNet net: network to attach
:return: nothing
"""
if self.net:
self.detachnet()
self.net = None
net.attach(self)
self.net = net
def detachnet(self):
"""
Detach from a network.
:return: nothing
"""
if self.net is not None:
self.net.detach(self)
def addaddr(self, addr):
"""
Add address.
:param str addr: address to add
:return: nothing
"""
self.addrlist.append(addr)
def deladdr(self, addr):
"""
Delete address.
:param str addr: address to delete
:return: nothing
"""
self.addrlist.remove(addr)
def sethwaddr(self, addr):
"""
Set hardware address.
:param core.misc.ipaddress.MacAddress addr: hardware address to set to.
:return: nothing
"""
self.hwaddr = addr
def getparam(self, key):
"""
Retrieve a parameter from the, or None if the parameter does not exist.
:param key: parameter to get value for
:return: parameter value
"""
return self._params.get(key)
def getparams(self):
"""
Return (key, value) pairs for parameters.
"""
parameters = []
for k in sorted(self._params.keys()):
parameters.append((k, self._params[k]))
return parameters
def setparam(self, key, value):
"""
Set a parameter value, returns True if the parameter has changed.
:param key: parameter name to set
:param value: parameter value
:return: True if parameter changed, False otherwise
"""
# treat None and 0 as unchanged values
current_value = self._params.get(key)
if current_value == value or current_value <= 0 and value <= 0:
return False
self._params[key] = value
return True
def swapparams(self, name):
"""
Swap out parameters dict for name. If name does not exist,
intialize it. This is for supporting separate upstream/downstream
parameters when two layer-2 nodes are linked together.
:param str name: name of parameter to swap
:return: nothing
"""
tmp = self._params
if not hasattr(self, name):
setattr(self, name, {})
self._params = getattr(self, name)
setattr(self, name, tmp)
def setposition(self, x, y, z):
"""
Dispatch position hook handler.
:param x: x position
:param y: y position
:param z: z position
:return: nothing
"""
self.poshook(self, x, y, z)

View file

@ -1,10 +1,10 @@
""" """
EMANE Bypass model for CORE EMANE Bypass model for CORE
""" """
from core.conf import ConfigGroup from core.config import ConfigGroup
from core.conf import Configuration from core.config import Configuration
from core.emane import emanemodel from core.emane import emanemodel
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
class EmaneBypassModel(emanemodel.EmaneModel): class EmaneBypassModel(emanemodel.EmaneModel):

View file

@ -7,7 +7,7 @@ import os
from lxml import etree from lxml import etree
from core.conf import ConfigGroup from core.config import ConfigGroup
from core.emane import emanemanifest from core.emane import emanemanifest
from core.emane import emanemodel from core.emane import emanemodel
from core.xml import emanexml from core.xml import emanexml
@ -80,7 +80,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
transport_type = "virtual" transport_type = "virtual"
if interface and interface.transport_type == "raw": if interface and interface.transport_type == "raw":
transport_type = "raw" transport_type = "raw"
transport_file = emanexml.transport_file_name(self.object_id, transport_type) transport_file = emanexml.transport_file_name(self.id, transport_type)
etree.SubElement(nem_element, "transport", definition=transport_file) etree.SubElement(nem_element, "transport", definition=transport_file)
# set shim configuration # set shim configuration
@ -125,7 +125,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
# TODO: batch these into multiple events per transmission # TODO: batch these into multiple events per transmission
# TODO: may want to split out seconds portion of delay and jitter # TODO: may want to split out seconds portion of delay and jitter
event = CommEffectEvent() event = CommEffectEvent()
emane_node = self.session.get_object(self.object_id) emane_node = self.session.get_node(self.id)
nemid = emane_node.getnemid(netif) nemid = emane_node.getnemid(netif)
nemid2 = emane_node.getnemid(netif2) nemid2 = emane_node.getnemid(netif2)
mbw = bw mbw = bw

View file

@ -6,14 +6,13 @@ import logging
import os import os
import threading import threading
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.api import coreapi from core.api.tlv import coreapi, dataconversion
from core.api import dataconversion from core.config import ConfigGroup
from core.conf import ConfigGroup from core.config import ConfigShim
from core.conf import ConfigShim from core.config import Configuration
from core.conf import Configuration from core.config import ModelManager
from core.conf import ModelManager
from core.emane import emanemanifest from core.emane import emanemanifest
from core.emane.bypass import EmaneBypassModel from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel from core.emane.commeffect import EmaneCommEffectModel
@ -21,15 +20,14 @@ from core.emane.emanemodel import EmaneModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.rfpipe import EmaneRfPipeModel from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel from core.emane.tdma import EmaneTdmaModel
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import ConfigFlags from core.emulator.enumerations import ConfigFlags
from core.enumerations import ConfigTlvs from core.emulator.enumerations import ConfigTlvs
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.misc import nodeutils from core.nodes import nodeutils
from core.misc import utils
from core.xml import emanexml from core.xml import emanexml
try: try:
@ -251,8 +249,8 @@ class EmaneManager(ModelManager):
logging.debug("emane setup") logging.debug("emane setup")
# TODO: drive this from the session object # TODO: drive this from the session object
with self.session._objects_lock: with self.session._nodes_lock:
for node in self.session.objects.itervalues(): for node in self.session.nodes.itervalues():
if nodeutils.is_node(node, NodeTypes.EMANE): if nodeutils.is_node(node, NodeTypes.EMANE):
logging.debug("adding emane node: id(%s) name(%s)", node.id, node.name) logging.debug("adding emane node: id(%s) name(%s)", node.id, node.name)
self.add_node(node) self.add_node(node)
@ -845,7 +843,7 @@ class EmaneManager(ModelManager):
# generate a node message for this location update # generate a node message for this location update
try: try:
node = self.session.get_object(n) node = self.session.get_node(n)
except KeyError: except KeyError:
logging.exception("location event NEM %s has no corresponding node %s" % (nemid, n)) logging.exception("location event NEM %s has no corresponding node %s" % (nemid, n))
return False return False
@ -906,8 +904,8 @@ class EmaneGlobalModel(EmaneModel):
ConfigGroup("NEM Parameters", emulator_len + 1, config_len) ConfigGroup("NEM Parameters", emulator_len + 1, config_len)
] ]
def __init__(self, session, object_id=None): def __init__(self, session, _id=None):
super(EmaneGlobalModel, self).__init__(session, object_id) super(EmaneGlobalModel, self).__init__(session, _id)
def build_xml_files(self, config, interface=None): def build_xml_files(self, config, interface=None):
raise NotImplementedError raise NotImplementedError

View file

@ -1,7 +1,7 @@
import logging import logging
from core.conf import Configuration from core.config import Configuration
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
manifest = None manifest = None
try: try:

View file

@ -4,11 +4,11 @@ Defines Emane Models used within CORE.
import logging import logging
import os import os
from core.conf import ConfigGroup from core.config import ConfigGroup
from core.conf import Configuration from core.config import Configuration
from core.emane import emanemanifest from core.emane import emanemanifest
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.mobility import WirelessModel from core.location.mobility import WirelessModel
from core.xml import emanexml from core.xml import emanexml
@ -105,7 +105,7 @@ class EmaneModel(WirelessModel):
transport_type = "virtual" transport_type = "virtual"
if interface and interface.transport_type == "raw": if interface and interface.transport_type == "raw":
transport_type = "raw" transport_type = "raw"
transport_name = emanexml.transport_file_name(self.object_id, transport_type) transport_name = emanexml.transport_file_name(self.id, transport_type)
# create nem xml file # create nem xml file
nem_file = os.path.join(self.session.session_dir, nem_name) nem_file = os.path.join(self.session.session_dir, nem_name)
@ -138,7 +138,7 @@ class EmaneModel(WirelessModel):
:return: :return:
""" """
try: try:
wlan = self.session.get_object(self.object_id) wlan = self.session.get_node(self.id)
wlan.setnempositions(moved_netifs) wlan.setnempositions(moved_netifs)
except KeyError: except KeyError:
logging.exception("error during update") logging.exception("error during update")

View file

@ -6,10 +6,10 @@ share the same MAC+PHY model.
import logging import logging
from core.coreobj import PyCoreNet from core.nodes.base import CoreNetworkBase
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
try: try:
from emane.events import LocationEvent from emane.events import LocationEvent
@ -20,7 +20,7 @@ except ImportError:
logging.debug("compatible emane python bindings not installed") logging.debug("compatible emane python bindings not installed")
class EmaneNet(PyCoreNet): class EmaneNet(CoreNetworkBase):
""" """
EMANE network base class. EMANE network base class.
""" """
@ -80,10 +80,10 @@ class EmaneNode(EmaneNet):
if model.config_type == RegisterTlvs.WIRELESS.value: if model.config_type == RegisterTlvs.WIRELESS.value:
# EmaneModel really uses values from ConfigurableManager # EmaneModel really uses values from ConfigurableManager
# when buildnemxml() is called, not during init() # when buildnemxml() is called, not during init()
self.model = model(session=self.session, object_id=self.id) self.model = model(session=self.session, _id=self.id)
self.model.update_config(config) self.model.update_config(config)
elif model.config_type == RegisterTlvs.MOBILITY.value: elif model.config_type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, object_id=self.id) self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config) self.mobility.update_config(config)
def setnemid(self, netif, nemid): def setnemid(self, netif, nemid):

View file

@ -5,11 +5,10 @@ tdma.py: EMANE TDMA model bindings for CORE
import logging import logging
import os import os
from core import constants from core import constants, utils
from core.conf import Configuration from core.config import Configuration
from core.emane import emanemodel from core.emane import emanemodel
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.misc import utils
class EmaneTdmaModel(emanemodel.EmaneModel): class EmaneTdmaModel(emanemodel.EmaneModel):
@ -49,7 +48,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
:return: nothing :return: nothing
""" """
# get configured schedule # get configured schedule
config = self.session.emane.get_configs(node_id=self.object_id, config_type=self.name) config = self.session.emane.get_configs(node_id=self.id, config_type=self.name)
if not config: if not config:
return return
schedule = config[self.schedule_name] schedule = config[self.schedule_name]

View file

@ -5,18 +5,16 @@ import signal
import sys import sys
import core.services import core.services
from core.coreobj import PyCoreNet from core.nodes.base import CoreNodeBase, CoreNetworkBase
from core.coreobj import PyCoreNode from core.emulator.data import NodeData
from core.data import NodeData
from core.emulator.emudata import LinkOptions from core.emulator.emudata import LinkOptions
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import nodemaps from core.nodes import nodeutils, nodemaps
from core.misc import nodeutils from core.services.coreservices import ServiceManager
from core.service import ServiceManager from core.emulator.session import Session
from core.session import Session
from core.xml.corexml import CoreXmlReader, CoreXmlWriter from core.xml.corexml import CoreXmlReader, CoreXmlWriter
@ -94,7 +92,7 @@ def is_net_node(node):
:return: True if object is an instance of a network node, False otherwise :return: True if object is an instance of a network node, False otherwise
:rtype: bool :rtype: bool
""" """
return isinstance(node, PyCoreNet) return isinstance(node, CoreNetworkBase)
def is_core_node(node): def is_core_node(node):
@ -105,7 +103,7 @@ def is_core_node(node):
:return: True if object is an instance of a core node, False otherwise :return: True if object is an instance of a core node, False otherwise
:rtype: bool :rtype: bool
""" """
return isinstance(node, PyCoreNode) return isinstance(node, CoreNodeBase)
class IdGen(object): class IdGen(object):
@ -149,8 +147,8 @@ class EmuSession(Session):
net_two = None net_two = None
# retrieve node one # retrieve node one
node_one = self.get_object(node_one_id) node_one = self.get_node(node_one_id)
node_two = self.get_object(node_two_id) node_two = self.get_node(node_two_id)
# both node ids are provided # both node ids are provided
tunnel = self.broker.gettunnel(node_one_id, node_two_id) tunnel = self.broker.gettunnel(node_one_id, node_two_id)
@ -245,7 +243,7 @@ class EmuSession(Session):
logging.info("adding link for peer to peer nodes: %s - %s", node_one.name, node_two.name) logging.info("adding link for peer to peer nodes: %s - %s", node_one.name, node_two.name)
ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER) ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER)
start = self.state > EventTypes.DEFINITION_STATE.value start = self.state > EventTypes.DEFINITION_STATE.value
net_one = self.add_object(cls=ptp_class, start=start) net_one = self.create_node(cls=ptp_class, start=start)
# node to network # node to network
if node_one and net_one: if node_one and net_one:
@ -366,7 +364,7 @@ class EmuSession(Session):
interface_one.detachnet() interface_one.detachnet()
interface_two.detachnet() interface_two.detachnet()
if net_one.numnetif() == 0: if net_one.numnetif() == 0:
self.delete_object(net_one.id) self.delete_node(net_one.id)
node_one.delnetif(interface_one.netindex) node_one.delnetif(interface_one.netindex)
node_two.delnetif(interface_two.netindex) node_two.delnetif(interface_two.netindex)
finally: finally:
@ -483,7 +481,7 @@ class EmuSession(Session):
if not _id: if not _id:
while True: while True:
_id = self.node_id_gen.next() _id = self.node_id_gen.next()
if _id not in self.objects: if _id not in self.nodes:
break break
# generate name if not provided # generate name if not provided
@ -493,7 +491,7 @@ class EmuSession(Session):
# create node # create node
logging.info("creating node(%s) id(%s) name(%s) start(%s)", node_class.__name__, _id, name, start) logging.info("creating node(%s) id(%s) name(%s) start(%s)", node_class.__name__, _id, name, start)
node = self.add_object(cls=node_class, _id=_id, name=name, start=start) node = self.create_node(cls=node_class, _id=_id, name=name, start=start)
# set node attributes # set node attributes
node.icon = node_options.icon node.icon = node_options.icon
@ -510,9 +508,9 @@ class EmuSession(Session):
self.services.add_services(node, node.type, node_options.services) self.services.add_services(node, node.type, node_options.services)
# boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes # boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes
is_boot_node = isinstance(node, PyCoreNode) and not nodeutils.is_node(node, NodeTypes.RJ45) is_boot_node = isinstance(node, CoreNodeBase) and not nodeutils.is_node(node, NodeTypes.RJ45)
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node: if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
self.write_objects() self.write_nodes()
self.add_remove_control_interface(node=node, remove=False) self.add_remove_control_interface(node=node, remove=False)
self.services.boot_services(node) self.services.boot_services(node)
@ -530,7 +528,7 @@ class EmuSession(Session):
result = False result = False
try: try:
# get node to update # get node to update
node = self.get_object(node_id) node = self.get_node(node_id)
# set node position and broadcast it # set node position and broadcast it
self.set_node_position(node, node_options) self.set_node_position(node, node_options)
@ -546,20 +544,6 @@ class EmuSession(Session):
return result return result
def delete_node(self, node_id):
"""
Delete a node from the session and check if session should shutdown, if no nodes are left.
:param int node_id: id of node to delete
:return: True if node deleted, False otherwise
:rtype: bool
"""
# delete node and check for session shutdown if a node was removed
result = self.custom_delete_object(node_id)
if result:
self.check_shutdown()
return result
def set_node_position(self, node, node_options): def set_node_position(self, node, node_options):
""" """
Set position for a node, use lat/lon/alt if needed. Set position for a node, use lat/lon/alt if needed.
@ -625,21 +609,6 @@ class EmuSession(Session):
self.set_state(EventTypes.SHUTDOWN_STATE, send_event=True) self.set_state(EventTypes.SHUTDOWN_STATE, send_event=True)
super(EmuSession, self).shutdown() super(EmuSession, self).shutdown()
def custom_delete_object(self, object_id):
"""
Remove an emulation object.
:param int object_id: object id to remove
:return: True if object deleted, False otherwise
"""
result = False
with self._objects_lock:
if object_id in self.objects:
obj = self.objects.pop(object_id)
obj.shutdown()
result = True
return result
def is_active(self): def is_active(self):
""" """
Determine if this session is considered to be active. (Runtime or Data collect states) Determine if this session is considered to be active. (Runtime or Data collect states)
@ -704,7 +673,7 @@ class EmuSession(Session):
:return: nothing :return: nothing
""" """
node = self.get_object(node_id) node = self.get_node(node_id)
if source_name is not None: if source_name is not None:
node.addfile(source_name, file_name) node.addfile(source_name, file_name)
@ -717,7 +686,7 @@ class EmuSession(Session):
:return: nothing :return: nothing
""" """
self.delete_objects() self.delete_nodes()
self.del_hooks() self.del_hooks()
self.broker.reset() self.broker.reset()
self.emane.reset() self.emane.reset()

View file

@ -1,7 +1,7 @@
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.misc.ipaddress import Ipv4Prefix from core.nodes.ipaddress import Ipv4Prefix
from core.misc.ipaddress import Ipv6Prefix from core.nodes.ipaddress import Ipv6Prefix
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
class NodeOptions(object): class NodeOptions(object):

View file

@ -5,6 +5,7 @@ that manages a CORE session.
import logging import logging
import os import os
import pwd
import random import random
import shutil import shutil
import subprocess import subprocess
@ -13,31 +14,29 @@ import threading
import time import time
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
import pwd import core.nodes.base
from core import constants, utils
from core import constants from core.api.tlv import coreapi
from core.api import coreapi from core.api.tlv.broker import CoreBroker
from core.broker import CoreBroker from core.config import ConfigurableManager
from core.conf import ConfigurableManager from core.config import ConfigurableOptions
from core.conf import ConfigurableOptions from core.config import Configuration
from core.conf import Configuration
from core.data import EventData
from core.data import ExceptionData
from core.emane.emanemanager import EmaneManager from core.emane.emanemanager import EmaneManager
from core.enumerations import ConfigDataTypes from core.emulator.data import EventData
from core.enumerations import EventTypes from core.emulator.data import ExceptionData
from core.enumerations import ExceptionLevels from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import EventTypes
from core.enumerations import RegisterTlvs from core.emulator.enumerations import ExceptionLevels
from core.location import CoreLocation from core.emulator.enumerations import NodeTypes
from core.misc import nodeutils from core.emulator.enumerations import RegisterTlvs
from core.misc import utils from core.location.corelocation import CoreLocation
from core.misc.event import EventLoop from core.location.event import EventLoop
from core.misc.ipaddress import MacAddress from core.location.mobility import MobilityManager
from core.mobility import MobilityManager from core.nodes import nodeutils
from core.netns import nodes from core.nodes.base import CoreNodeBase
from core.sdt import Sdt from core.nodes.ipaddress import MacAddress
from core.service import CoreServices from core.plugins.sdt import Sdt
from core.services.coreservices import CoreServices
from core.xml import corexml, corexmldeployment from core.xml import corexml, corexmldeployment
@ -67,9 +66,9 @@ class Session(object):
self.user = None self.user = None
self.event_loop = EventLoop() self.event_loop = EventLoop()
# dict of objects: all nodes and nets # dict of nodes: all nodes and nets
self.objects = {} self.nodes = {}
self._objects_lock = threading.Lock() self._nodes_lock = threading.Lock()
# TODO: should the default state be definition? # TODO: should the default state be definition?
self.state = EventTypes.NONE.value self.state = EventTypes.NONE.value
@ -110,15 +109,15 @@ class Session(object):
def shutdown(self): def shutdown(self):
""" """
Shutdown all emulation objects and remove the session directory. Shutdown all session nodes and remove the session directory.
""" """
# shutdown/cleanup feature helpers # shutdown/cleanup feature helpers
self.emane.shutdown() self.emane.shutdown()
self.broker.shutdown() self.broker.shutdown()
self.sdt.shutdown() self.sdt.shutdown()
# delete all current objects # delete all current nodes
self.delete_objects() self.delete_nodes()
# remove this sessions working directory # remove this sessions working directory
preserve = self.options.get_config("preservedir") == "1" preserve = self.options.get_config("preservedir") == "1"
@ -464,93 +463,87 @@ class Session(object):
""" """
Return a unique, new node id. Return a unique, new node id.
""" """
with self._objects_lock: with self._nodes_lock:
while True: while True:
object_id = random.randint(1, 0xFFFF) node_id = random.randint(1, 0xFFFF)
if object_id not in self.objects: if node_id not in self.nodes:
break break
return object_id return node_id
def add_object(self, cls, *clsargs, **clskwds): def create_node(self, cls, *clsargs, **clskwds):
""" """
Create an emulation node. Create an emulation node.
:param class cls: object class to add :param class cls: node class to create
:param list clsargs: list of arguments for the class to create :param list clsargs: list of arguments for the class to create
:param dict clskwds: dictionary of arguments for the class to create :param dict clskwds: dictionary of arguments for the class to create
:return: the created class instance :return: the created node instance
""" """
node = cls(self, *clsargs, **clskwds) node = cls(self, *clsargs, **clskwds)
with self._objects_lock: with self._nodes_lock:
if node.id in self.objects: if node.id in self.nodes:
node.shutdown() node.shutdown()
raise KeyError("duplicate node id %s for %s" % (node.id, node.name)) raise KeyError("duplicate node id %s for %s" % (node.id, node.name))
self.objects[node.id] = node self.nodes[node.id] = node
return node return node
def get_object(self, object_id): def get_node(self, _id):
""" """
Get an emulation object. Get a session node.
:param int object_id: object id to retrieve :param int _id: node id to retrieve
:return: object for the given id :return: node for the given id
:rtype: core.coreobj.PyCoreNode :rtype: core.nodes.base.CoreNode
""" """
if object_id not in self.objects: if _id not in self.nodes:
raise KeyError("unknown object id %s" % object_id) raise KeyError("unknown node id %s" % _id)
return self.objects[object_id] return self.nodes[_id]
def get_object_by_name(self, name): def delete_node(self, _id):
""" """
Get an emulation object using its name attribute. Delete a node from the session and check if session should shutdown, if no nodes are left.
:param str name: name of object to retrieve :param int _id: id of node to delete
:return: object for the name given :return: True if node deleted, False otherwise
:rtype: bool
""" """
with self._objects_lock: # delete node and check for session shutdown if a node was removed
for obj in self.objects.itervalues(): result = False
if hasattr(obj, "name") and obj.name == name: with self._nodes_lock:
return obj if _id in self.nodes:
raise KeyError("unknown object with name %s" % name) node = self.nodes.pop(_id)
node.shutdown()
result = True
def delete_object(self, object_id): if result:
""" self.check_shutdown()
Remove an emulation object.
:param int object_id: object id to remove return result
:return: nothing
"""
with self._objects_lock:
try:
obj = self.objects.pop(object_id)
obj.shutdown()
except KeyError:
logging.error("failed to remove object, object with id was not found: %s", object_id)
def delete_objects(self): def delete_nodes(self):
""" """
Clear the objects dictionary, and call shutdown for each object. Clear the nodes dictionary, and call shutdown for each node.
""" """
with self._objects_lock: with self._nodes_lock:
while self.objects: while self.nodes:
_, obj = self.objects.popitem() _, node = self.nodes.popitem()
obj.shutdown() node.shutdown()
def write_objects(self): def write_nodes(self):
""" """
Write objects to a 'nodes' file in the session dir. Write nodes to a 'nodes' file in the session dir.
The 'nodes' file lists: number, name, api-type, class-type The 'nodes' file lists: number, name, api-type, class-type
""" """
try: try:
nodes_file = open(os.path.join(self.session_dir, "nodes"), "w") with self._nodes_lock:
with self._objects_lock: file_path = os.path.join(self.session_dir, "nodes")
for object_id in sorted(self.objects.keys()): with open(file_path, "w") as f:
obj = self.objects[object_id] for _id in sorted(self.nodes.keys()):
nodes_file.write("%s %s %s %s\n" % (object_id, obj.name, obj.apitype, type(obj))) node = self.nodes[_id]
nodes_file.close() f.write("%s %s %s %s\n" % (_id, node.name, node.apitype, type(node)))
except IOError: except IOError:
logging.exception("error writing nodes file") logging.exception("error writing nodes file")
@ -560,21 +553,21 @@ class Session(object):
""" """
logging.info("session id=%s name=%s state=%s", self.id, self.name, self.state) logging.info("session id=%s name=%s state=%s", self.id, self.name, self.state)
logging.info("file=%s thumbnail=%s node_count=%s/%s", logging.info("file=%s thumbnail=%s node_count=%s/%s",
self.file_name, self.thumbnail, self.get_node_count(), len(self.objects)) self.file_name, self.thumbnail, self.get_node_count(), len(self.nodes))
def exception(self, level, source, object_id, text): def exception(self, level, source, node_id, text):
""" """
Generate and broadcast an exception event. Generate and broadcast an exception event.
:param str level: exception level :param str level: exception level
:param str source: source name :param str source: source name
:param int object_id: object id :param int node_id: node related to exception
:param str text: exception message :param str text: exception message
:return: nothing :return: nothing
""" """
exception_data = ExceptionData( exception_data = ExceptionData(
node=object_id, node=node_id,
session=str(self.id), session=str(self.id),
level=level, level=level,
source=source, source=source,
@ -591,8 +584,8 @@ class Session(object):
for transition to the runtime state. for transition to the runtime state.
""" """
# write current objects out to session directory file # write current nodes out to session directory file
self.write_objects() self.write_nodes()
# controlnet may be needed by some EMANE models # controlnet may be needed by some EMANE models
self.add_remove_control_interface(node=None, remove=False) self.add_remove_control_interface(node=None, remove=False)
@ -626,12 +619,12 @@ class Session(object):
that are not considered in the GUI's node count. that are not considered in the GUI's node count.
""" """
with self._objects_lock: with self._nodes_lock:
count = len([x for x in self.objects.itervalues() count = len([x for x in self.nodes.itervalues()
if not nodeutils.is_node(x, (NodeTypes.PEER_TO_PEER, NodeTypes.CONTROL_NET))]) if not nodeutils.is_node(x, (NodeTypes.PEER_TO_PEER, NodeTypes.CONTROL_NET))])
# on Linux, GreTapBridges are auto-created, not part of GUI's node count # on Linux, GreTapBridges are auto-created, not part of GUI's node count
count -= len([x for x in self.objects.itervalues() count -= len([x for x in self.nodes.itervalues()
if nodeutils.is_node(x, NodeTypes.TAP_BRIDGE) and not nodeutils.is_node(x, NodeTypes.TUNNEL)]) if nodeutils.is_node(x, NodeTypes.TAP_BRIDGE) and not nodeutils.is_node(x, NodeTypes.TUNNEL)])
return count return count
@ -668,10 +661,10 @@ class Session(object):
self.event_loop.stop() self.event_loop.stop()
# stop node services # stop node services
with self._objects_lock: with self._nodes_lock:
for obj in self.objects.itervalues(): for obj in self.nodes.itervalues():
# TODO: determine if checking for CoreNode alone is ok # TODO: determine if checking for CoreNode alone is ok
if isinstance(obj, nodes.PyCoreNode): if isinstance(obj, core.nodes.base.CoreNodeBase):
self.services.stop_services(obj) self.services.stop_services(obj)
# shutdown emane # shutdown emane
@ -715,14 +708,14 @@ class Session(object):
messages to the GUI for node messages that had the status messages to the GUI for node messages that had the status
request flag. request flag.
""" """
with self._objects_lock: with self._nodes_lock:
pool = ThreadPool() pool = ThreadPool()
results = [] results = []
start = time.time() start = time.time()
for obj in self.objects.itervalues(): for obj in self.nodes.itervalues():
# TODO: PyCoreNode is not the type to check # TODO: PyCoreNode is not the type to check
if isinstance(obj, nodes.PyCoreNode) and not nodeutils.is_node(obj, NodeTypes.RJ45): if isinstance(obj, CoreNodeBase) and not nodeutils.is_node(obj, NodeTypes.RJ45):
# add a control interface if configured # add a control interface if configured
logging.info("booting node: %s", obj.name) logging.info("booting node: %s", obj.name)
self.add_remove_control_interface(node=obj, remove=False) self.add_remove_control_interface(node=obj, remove=False)
@ -786,10 +779,10 @@ class Session(object):
return index return index
return -1 return -1
def get_control_net_object(self, net_index): def get_control_net(self, net_index):
# TODO: all nodes use an integer id and now this wants to use a string # TODO: all nodes use an integer id and now this wants to use a string
object_id = "ctrl%dnet" % net_index _id = "ctrl%dnet" % net_index
return self.get_object(object_id) return self.get_node(_id)
def add_remove_control_net(self, net_index, remove=False, conf_required=True): def add_remove_control_net(self, net_index, remove=False, conf_required=True):
""" """
@ -801,8 +794,8 @@ class Session(object):
:param int net_index: network index :param int net_index: network index
:param bool remove: flag to check if it should be removed :param bool remove: flag to check if it should be removed
:param bool conf_required: flag to check if conf is required :param bool conf_required: flag to check if conf is required
:return: control net object :return: control net node
:rtype: core.netns.nodes.CtrlNet :rtype: core.nodes.network.CtrlNet
""" """
logging.debug("add/remove control net: index(%s) remove(%s) conf_required(%s)", net_index, remove, conf_required) logging.debug("add/remove control net: index(%s) remove(%s) conf_required(%s)", net_index, remove, conf_required)
prefix_spec_list = self.get_control_net_prefixes() prefix_spec_list = self.get_control_net_prefixes()
@ -820,10 +813,10 @@ class Session(object):
# return any existing controlnet bridge # return any existing controlnet bridge
try: try:
control_net = self.get_control_net_object(net_index) control_net = self.get_control_net(net_index)
if remove: if remove:
self.delete_object(control_net.id) self.delete_node(control_net.id)
return None return None
return control_net return control_net
@ -832,7 +825,7 @@ class Session(object):
return None return None
# build a new controlnet bridge # build a new controlnet bridge
object_id = "ctrl%dnet" % net_index _id = "ctrl%dnet" % net_index
# use the updown script for control net 0 only. # use the updown script for control net 0 only.
updown_script = None updown_script = None
@ -887,16 +880,16 @@ class Session(object):
prefix = prefixes[0] prefix = prefixes[0]
control_net_class = nodeutils.get_node_class(NodeTypes.CONTROL_NET) control_net_class = nodeutils.get_node_class(NodeTypes.CONTROL_NET)
control_net = self.add_object(cls=control_net_class, _id=object_id, prefix=prefix, control_net = self.create_node(cls=control_net_class, _id=_id, prefix=prefix,
assign_address=assign_address, assign_address=assign_address,
updown_script=updown_script, serverintf=server_interface) updown_script=updown_script, serverintf=server_interface)
# tunnels between controlnets will be built with Broker.addnettunnels() # tunnels between controlnets will be built with Broker.addnettunnels()
# TODO: potentially remove documentation saying object ids are ints # TODO: potentially remove documentation saying node ids are ints
# TODO: need to move broker code out of the session object # TODO: need to move broker code out of the session object
self.broker.addnet(object_id) self.broker.addnet(_id)
for server in self.broker.getservers(): for server in self.broker.getservers():
self.broker.addnodemap(server, object_id) self.broker.addnodemap(server, _id)
return control_net return control_net
@ -908,7 +901,7 @@ class Session(object):
If conf_reqd is False, the control network may be built even If conf_reqd is False, the control network may be built even
when the user has not configured one (e.g. for EMANE.) when the user has not configured one (e.g. for EMANE.)
:param core.netns.nodes.CoreNode node: node to add or remove control interface :param core.netns.vnode.CoreNode node: node to add or remove control interface
:param int net_index: network index :param int net_index: network index
:param bool remove: flag to check if it should be removed :param bool remove: flag to check if it should be removed
:param bool conf_required: flag to check if conf is required :param bool conf_required: flag to check if conf is required
@ -954,9 +947,9 @@ class Session(object):
return return
try: try:
control_net = self.get_control_net_object(net_index) control_net = self.get_control_net(net_index)
except KeyError: except KeyError:
logging.exception("error retrieving control net object") logging.exception("error retrieving control net node")
return return
header = "CORE session %s host entries" % self.id header = "CORE session %s host entries" % self.id
@ -991,7 +984,7 @@ class Session(object):
start of the runtime state. start of the runtime state.
:param event_time: event time :param event_time: event time
:param core.netns.nodes.CoreNode node: node to add event for :param core.netns.vnode.CoreNode node: node to add event for
:param str name: name of event :param str name: name of event
:param data: data for event :param data: data for event
:return: nothing :return: nothing
@ -1029,13 +1022,13 @@ class Session(object):
if not node_id: if not node_id:
utils.mute_detach(data) utils.mute_detach(data)
else: else:
node = self.get_object(node_id) node = self.get_node(node_id)
node.cmd(data, wait=False) node.cmd(data, wait=False)
class SessionConfig(ConfigurableManager, ConfigurableOptions): class SessionConfig(ConfigurableManager, ConfigurableOptions):
""" """
Session configuration object. Provides session configuration.
""" """
name = "session" name = "session"
options = [ options = [

View file

@ -7,8 +7,8 @@ https://pypi.python.org/pypi/utm (version 0.3.0).
import logging import logging
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.misc import utm from core.location import utm
class CoreLocation(object): class CoreLocation(object):

View file

@ -9,22 +9,22 @@ import os
import threading import threading
import time import time
from core.conf import ConfigGroup from core.config import ConfigGroup
from core.conf import ConfigurableOptions from core.config import ConfigurableOptions
from core.conf import Configuration from core.config import Configuration
from core.conf import ModelManager from core.config import ModelManager
from core.coreobj import PyCoreNode from core.nodes.base import CoreNodeBase
from core.data import EventData from core.emulator.data import EventData
from core.data import LinkData from core.emulator.data import LinkData
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTlvs
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.misc import utils from core import utils
from core.misc.ipaddress import IpAddress from core.nodes.ipaddress import IpAddress
class MobilityManager(ModelManager): class MobilityManager(ModelManager):
@ -67,7 +67,7 @@ class MobilityManager(ModelManager):
logging.info("node mobility configurations: %s", self.get_all_configs(node_id)) logging.info("node mobility configurations: %s", self.get_all_configs(node_id))
try: try:
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
except KeyError: except KeyError:
logging.warn("skipping mobility configuration for unknown node: %s", node_id) logging.warn("skipping mobility configuration for unknown node: %s", node_id)
continue continue
@ -98,7 +98,7 @@ class MobilityManager(ModelManager):
name = event_data.name name = event_data.name
try: try:
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
except KeyError: except KeyError:
logging.exception("Ignoring event for model '%s', unknown node '%s'", name, node_id) logging.exception("Ignoring event for model '%s', unknown node '%s'", name, node_id)
return return
@ -152,7 +152,7 @@ class MobilityManager(ModelManager):
data += " end=%d" % int(model.endtime) data += " end=%d" % int(model.endtime)
event_data = EventData( event_data = EventData(
node=model.object_id, node=model.id,
event_type=event_type, event_type=event_type,
name="mobility:%s" % model.name, name="mobility:%s" % model.name,
data=data, data=data,
@ -173,7 +173,7 @@ class MobilityManager(ModelManager):
""" """
for node_id in self.nodes(): for node_id in self.nodes():
try: try:
node = self.session.get_object(node_id) node = self.session.get_node(node_id)
except KeyError: except KeyError:
continue continue
if node.model: if node.model:
@ -213,7 +213,7 @@ class MobilityManager(ModelManager):
return return
if nn[1] in self.session.broker.physical_nodes: if nn[1] in self.session.broker.physical_nodes:
# record the fact that this PhysicalNode is linked to a net # record the fact that this PhysicalNode is linked to a net
dummy = PyCoreNode(session=self.session, _id=nn[1], name="n%d" % nn[1], start=False) dummy = CoreNodeBase(session=self.session, _id=nn[1], name="n%d" % nn[1], start=False)
self.addphys(nn[0], dummy) self.addphys(nn[0], dummy)
# TODO: remove need to handling old style messages # TODO: remove need to handling old style messages
@ -265,15 +265,15 @@ class WirelessModel(ConfigurableOptions):
bitmap = None bitmap = None
position_callback = None position_callback = None
def __init__(self, session, object_id): def __init__(self, session, _id):
""" """
Create a WirelessModel instance. Create a WirelessModel instance.
:param core.session.Session session: core session we are tied to :param core.session.Session session: core session we are tied to
:param int object_id: object id :param int _id: object id
""" """
self.session = session self.session = session
self.object_id = object_id self.id = _id
def all_link_data(self, flags): def all_link_data(self, flags):
""" """
@ -329,17 +329,17 @@ class BasicRangeModel(WirelessModel):
ConfigGroup("Basic Range Parameters", 1, len(cls.configurations())) ConfigGroup("Basic Range Parameters", 1, len(cls.configurations()))
] ]
def __init__(self, session, object_id): def __init__(self, session, _id):
""" """
Create a BasicRangeModel instance. Create a BasicRangeModel instance.
:param core.session.Session session: related core session :param core.session.Session session: related core session
:param int object_id: object id :param int _id: object id
:param dict config: values :param dict config: values
""" """
super(BasicRangeModel, self).__init__(session=session, object_id=object_id) super(BasicRangeModel, self).__init__(session=session, _id=_id)
self.session = session self.session = session
self.wlan = session.get_object(object_id) self.wlan = session.get_node(_id)
self._netifs = {} self._netifs = {}
self._netifslock = threading.Lock() self._netifslock = threading.Lock()
@ -605,15 +605,15 @@ class WayPointMobility(WirelessModel):
STATE_RUNNING = 1 STATE_RUNNING = 1
STATE_PAUSED = 2 STATE_PAUSED = 2
def __init__(self, session, object_id): def __init__(self, session, _id):
""" """
Create a WayPointMobility instance. Create a WayPointMobility instance.
:param core.session.Session session: CORE session instance :param core.session.Session session: CORE session instance
:param int object_id: object id :param int _id: object id
:return: :return:
""" """
super(WayPointMobility, self).__init__(session=session, object_id=object_id) super(WayPointMobility, self).__init__(session=session, _id=_id)
self.state = self.STATE_STOPPED self.state = self.STATE_STOPPED
self.queue = [] self.queue = []
@ -622,7 +622,7 @@ class WayPointMobility(WirelessModel):
self.initial = {} self.initial = {}
self.lasttime = None self.lasttime = None
self.endtime = None self.endtime = None
self.wlan = session.get_object(object_id) self.wlan = session.get_node(_id)
# these are really set in child class via confmatrix # these are really set in child class via confmatrix
self.loop = False self.loop = False
self.refresh_ms = 50 self.refresh_ms = 50
@ -700,7 +700,7 @@ class WayPointMobility(WirelessModel):
Calculate next node location and update its coordinates. Calculate next node location and update its coordinates.
Returns True if the node's position has changed. Returns True if the node's position has changed.
:param core.netns.nodes.CoreNode node: node to move :param core.netns.vnode.CoreNode node: node to move
:param dt: move factor :param dt: move factor
:return: True if node was moved, False otherwise :return: True if node was moved, False otherwise
:rtype: bool :rtype: bool
@ -830,7 +830,7 @@ class WayPointMobility(WirelessModel):
without invoking the interface poshook callback that may perform without invoking the interface poshook callback that may perform
range calculation. range calculation.
:param core.netns.nodes.CoreNode node: node to set position for :param core.netns.vnode.CoreNode node: node to set position for
:param x: x position :param x: x position
:param y: y position :param y: y position
:param z: z position :param z: z position
@ -923,15 +923,15 @@ class Ns2ScriptedMobility(WayPointMobility):
ConfigGroup("ns-2 Mobility Script Parameters", 1, len(cls.configurations())) ConfigGroup("ns-2 Mobility Script Parameters", 1, len(cls.configurations()))
] ]
def __init__(self, session, object_id): def __init__(self, session, _id):
""" """
Creates a Ns2ScriptedMobility instance. Creates a Ns2ScriptedMobility instance.
:param core.session.Session session: CORE session instance :param core.session.Session session: CORE session instance
:param int object_id: object id :param int _id: object id
:param config: values :param config: values
""" """
super(Ns2ScriptedMobility, self).__init__(session=session, object_id=object_id) super(Ns2ScriptedMobility, self).__init__(session=session, _id=_id)
self._netifs = {} self._netifs = {}
self._netifslock = threading.Lock() self._netifslock = threading.Lock()
@ -946,7 +946,7 @@ class Ns2ScriptedMobility(WayPointMobility):
def update_config(self, config): def update_config(self, config):
self.file = config["file"] self.file = config["file"]
logging.info("ns-2 scripted mobility configured for WLAN %d using file: %s", self.object_id, self.file) logging.info("ns-2 scripted mobility configured for WLAN %d using file: %s", self.id, self.file)
self.refresh_ms = int(config["refresh_ms"]) self.refresh_ms = int(config["refresh_ms"])
self.loop = config["loop"].lower() == "on" self.loop = config["loop"].lower() == "on"
self.autostart = config["autostart"] self.autostart = config["autostart"]

View file

@ -1,246 +0,0 @@
#!/usr/bin/env python
# this file is from http://pygps.org/
# Lat Long - UTM, UTM - Lat Long conversions
from math import pi, sin, cos, tan, sqrt
# LatLong- UTM conversion..h
# definitions for lat/long to UTM and UTM to lat/lng conversions
# include <string.h>
_deg2rad = pi / 180.0
_rad2deg = 180.0 / pi
_EquatorialRadius = 2
_eccentricitySquared = 3
_ellipsoid = [
# id, Ellipsoid name, Equatorial Radius, square of eccentricity
# first once is a placeholder only, To allow array indices to match id numbers
[-1, "Placeholder", 0, 0],
[1, "Airy", 6377563, 0.00667054],
[2, "Australian National", 6378160, 0.006694542],
[3, "Bessel 1841", 6377397, 0.006674372],
[4, "Bessel 1841 (Nambia] ", 6377484, 0.006674372],
[5, "Clarke 1866", 6378206, 0.006768658],
[6, "Clarke 1880", 6378249, 0.006803511],
[7, "Everest", 6377276, 0.006637847],
[8, "Fischer 1960 (Mercury] ", 6378166, 0.006693422],
[9, "Fischer 1968", 6378150, 0.006693422],
[10, "GRS 1967", 6378160, 0.006694605],
[11, "GRS 1980", 6378137, 0.00669438],
[12, "Helmert 1906", 6378200, 0.006693422],
[13, "Hough", 6378270, 0.00672267],
[14, "International", 6378388, 0.00672267],
[15, "Krassovsky", 6378245, 0.006693422],
[16, "Modified Airy", 6377340, 0.00667054],
[17, "Modified Everest", 6377304, 0.006637847],
[18, "Modified Fischer 1960", 6378155, 0.006693422],
[19, "South American 1969", 6378160, 0.006694542],
[20, "WGS 60", 6378165, 0.006693422],
[21, "WGS 66", 6378145, 0.006694542],
[22, "WGS-72", 6378135, 0.006694318],
[23, "WGS-84", 6378137, 0.00669438]
]
# Reference ellipsoids derived from Peter H. Dana's website-
# http://www.utexas.edu/depts/grg/gcraft/notes/datum/elist.html
# Department of Geography, University of Texas at Austin
# Internet: pdana@mail.utexas.edu
# 3/22/95
# Source
# Defense Mapping Agency. 1987b. DMA Technical Report: Supplement to Department of Defense World Geodetic System
# 1984 Technical Report. Part I and II. Washington, DC: Defense Mapping Agency
# def LLtoUTM(int ReferenceEllipsoid, const double Lat, const double Long,
# double &UTMNorthing, double &UTMEasting, char* UTMZone)
def LLtoUTM(ReferenceEllipsoid, Lat, Long, zone=None):
"""converts lat/long to UTM coords. Equations from USGS Bulletin 1532
East Longitudes are positive, West longitudes are negative.
North latitudes are positive, South latitudes are negative
Lat and Long are in decimal degrees
Written by Chuck Gantz- chuck.gantz@globalstar.com"""
a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
k0 = 0.9996
# Make sure the longitude is between -180.00 .. 179.9
LongTemp = (Long + 180) - int((Long + 180) / 360) * 360 - 180 # -180.00 .. 179.9
LatRad = Lat * _deg2rad
LongRad = LongTemp * _deg2rad
if zone is None:
ZoneNumber = int((LongTemp + 180) / 6) + 1
else:
ZoneNumber = zone
if Lat >= 56.0 and Lat < 64.0 and LongTemp >= 3.0 and LongTemp < 12.0:
ZoneNumber = 32
# Special zones for Svalbard
if Lat >= 72.0 and Lat < 84.0:
if LongTemp >= 0.0 and LongTemp < 9.0:
ZoneNumber = 31
elif LongTemp >= 9.0 and LongTemp < 21.0:
ZoneNumber = 33
elif LongTemp >= 21.0 and LongTemp < 33.0:
ZoneNumber = 35
elif LongTemp >= 33.0 and LongTemp < 42.0:
ZoneNumber = 37
LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3 # +3 puts origin in middle of zone
LongOriginRad = LongOrigin * _deg2rad
# compute the UTM Zone from the latitude and longitude
UTMZone = "%d%c" % (ZoneNumber, _UTMLetterDesignator(Lat))
eccPrimeSquared = (eccSquared) / (1 - eccSquared)
N = a / sqrt(1 - eccSquared * sin(LatRad) * sin(LatRad))
T = tan(LatRad) * tan(LatRad)
C = eccPrimeSquared * cos(LatRad) * cos(LatRad)
A = cos(LatRad) * (LongRad - LongOriginRad)
M = a * ((1
- eccSquared / 4
- 3 * eccSquared * eccSquared / 64
- 5 * eccSquared * eccSquared * eccSquared / 256) * LatRad
- (3 * eccSquared / 8
+ 3 * eccSquared * eccSquared / 32
+ 45 * eccSquared * eccSquared * eccSquared / 1024) * sin(2 * LatRad)
+ (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * sin(4 * LatRad)
- (35 * eccSquared * eccSquared * eccSquared / 3072) * sin(6 * LatRad))
UTMEasting = (k0 * N * (A + (1 - T + C) * A * A * A / 6
+ (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120)
+ 500000.0)
UTMNorthing = (k0 * (M + N * tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24
+ (61
- 58 * T
+ T * T
+ 600 * C
- 330 * eccPrimeSquared) * A * A * A * A * A * A / 720)))
if Lat < 0:
UTMNorthing = UTMNorthing + 10000000.0; # 10000000 meter offset for southern hemisphere
return (UTMZone, UTMEasting, UTMNorthing)
def _UTMLetterDesignator(Lat):
"""This routine determines the correct UTM letter designator for the given
latitude returns 'Z' if latitude is outside the UTM limits of 84N to 80S
Written by Chuck Gantz- chuck.gantz@globalstar.com"""
if 84 >= Lat >= 72:
return 'X'
elif 72 > Lat >= 64:
return 'W'
elif 64 > Lat >= 56:
return 'V'
elif 56 > Lat >= 48:
return 'U'
elif 48 > Lat >= 40:
return 'T'
elif 40 > Lat >= 32:
return 'S'
elif 32 > Lat >= 24:
return 'R'
elif 24 > Lat >= 16:
return 'Q'
elif 16 > Lat >= 8:
return 'P'
elif 8 > Lat >= 0:
return 'N'
elif 0 > Lat >= -8:
return 'M'
elif -8 > Lat >= -16:
return 'L'
elif -16 > Lat >= -24:
return 'K'
elif -24 > Lat >= -32:
return 'J'
elif -32 > Lat >= -40:
return 'H'
elif -40 > Lat >= -48:
return 'G'
elif -48 > Lat >= -56:
return 'F'
elif -56 > Lat >= -64:
return 'E'
elif -64 > Lat >= -72:
return 'D'
elif -72 > Lat >= -80:
return 'C'
else:
return 'Z' # if the Latitude is outside the UTM limits
# void UTMtoLL(int ReferenceEllipsoid, const double UTMNorthing, const double UTMEasting, const char* UTMZone,
# double& Lat, double& Long )
def UTMtoLL(ReferenceEllipsoid, northing, easting, zone):
"""converts UTM coords to lat/long. Equations from USGS Bulletin 1532
East Longitudes are positive, West longitudes are negative.
North latitudes are positive, South latitudes are negative
Lat and Long are in decimal degrees.
Written by Chuck Gantz- chuck.gantz@globalstar.com
Converted to Python by Russ Nelson <nelson@crynwr.com>"""
k0 = 0.9996
a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
e1 = (1 - sqrt(1 - eccSquared)) / (1 + sqrt(1 - eccSquared))
# NorthernHemisphere; //1 for northern hemispher, 0 for southern
x = easting - 500000.0 # remove 500,000 meter offset for longitude
y = northing
ZoneLetter = zone[-1]
ZoneNumber = int(zone[:-1])
if ZoneLetter >= 'N':
NorthernHemisphere = 1 # point is in northern hemisphere
else:
NorthernHemisphere = 0 # point is in southern hemisphere
y -= 10000000.0 # remove 10,000,000 meter offset used for southern hemisphere
LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3 # +3 puts origin in middle of zone
eccPrimeSquared = (eccSquared) / (1 - eccSquared)
M = y / k0
mu = M / (
a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256))
phi1Rad = (mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * sin(2 * mu)
+ (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * sin(4 * mu)
+ (151 * e1 * e1 * e1 / 96) * sin(6 * mu))
phi1 = phi1Rad * _rad2deg;
N1 = a / sqrt(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad))
T1 = tan(phi1Rad) * tan(phi1Rad)
C1 = eccPrimeSquared * cos(phi1Rad) * cos(phi1Rad)
R1 = a * (1 - eccSquared) / pow(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad), 1.5)
D = x / (N1 * k0)
Lat = phi1Rad - (N1 * tan(phi1Rad) / R1) * (
D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24
+ (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720)
Lat = Lat * _rad2deg
Long = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (
5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1)
* D * D * D * D * D / 120) / cos(phi1Rad)
Long = LongOrigin + Long * _rad2deg
return (Lat, Long)
if __name__ == '__main__':
(z, e, n) = LLtoUTM(23, 45.00, -75.00)
print z, e, n
print UTMtoLL(23, n, e, z)

View file

@ -1,28 +0,0 @@
"""
Provides default node maps that can be used to run core with.
"""
from core.emane.nodes import EmaneNet
from core.emane.nodes import EmaneNode
from core.enumerations import NodeTypes
from core.netns import nodes
from core.netns.vnet import GreTapBridge
from core.phys import pnodes
# legacy core nodes, that leverage linux bridges
NODES = {
NodeTypes.DEFAULT: nodes.CoreNode,
NodeTypes.PHYSICAL: pnodes.PhysicalNode,
NodeTypes.TBD: None,
NodeTypes.SWITCH: nodes.SwitchNode,
NodeTypes.HUB: nodes.HubNode,
NodeTypes.WIRELESS_LAN: nodes.WlanNode,
NodeTypes.RJ45: nodes.RJ45Node,
NodeTypes.TUNNEL: nodes.TunnelNode,
NodeTypes.KTUNNEL: None,
NodeTypes.EMANE: EmaneNode,
NodeTypes.EMANE_NET: EmaneNet,
NodeTypes.TAP_BRIDGE: GreTapBridge,
NodeTypes.PEER_TO_PEER: nodes.PtpNet,
NodeTypes.CONTROL_NET: nodes.CtrlNet
}

View file

@ -1,172 +0,0 @@
"""
quagga.py: helper class for generating Quagga configuration.
"""
from string import Template
from core.misc import utils
def addrstr(x):
if x.find(".") >= 0:
return "ip address %s" % x
elif x.find(":") >= 0:
return "ipv6 address %s" % x
else:
raise ValueError("invalid address: %s" % x)
class NetIf(object):
"""
Represents a network interface.
"""
def __init__(self, name, addrlist=None):
"""
Create a NetIf instance.
:param str name: interface name
:param addrlist: address list for the interface
"""
self.name = name
if addrlist:
self.addrlist = addrlist
else:
self.addrlist = []
class Conf(object):
"""
Provides a configuration object.
"""
template = Template("")
def __init__(self, **kwargs):
"""
Create a Conf instance.
:param dict kwargs: configuration keyword arguments
"""
self.kwargs = kwargs
def __str__(self):
"""
Provides a string representation of a configuration object.
:return: string representation
:rtype: str
"""
tmp = self.template.substitute(**self.kwargs)
if tmp[-1] == "\n":
tmp = tmp[:-1]
return tmp
class QuaggaOSPF6Interface(Conf):
"""
Provides quagga ospf6 interface functionality.
"""
AF_IPV6_ID = 0
AF_IPV4_ID = 65
template = Template("""\
interface $interface
$addr
ipv6 ospf6 instance-id $instanceid
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 11
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 network $network
ipv6 ospf6 diffhellos
ipv6 ospf6 adjacencyconnectivity uniconnected
ipv6 ospf6 lsafullness mincostlsa
""")
# ip address $ipaddr/32
# ipv6 ospf6 simhelloLLtoULRecv :$simhelloport
# !$ipaddr:$simhelloport
def __init__(self, netif, instanceid=AF_IPV4_ID, network="manet-designated-router", **kwargs):
"""
Create a QuaggaOSPF6Interface instance.
:param netif: network interface
:param int instanceid: instance id
:param network: network
:param dict kwargs: keyword arguments
"""
self.netif = netif
addr = "\n ".join(map(addrstr, netif.addrlist))
self.instanceid = instanceid
self.network = network
Conf.__init__(self, interface=netif.name, addr=addr,
instanceid=instanceid, network=network, **kwargs)
def name(self):
"""
Retrieve network interface name.
:return: network interface name
:rtype: str
"""
return self.netif.name
class QuaggaOSPF6(Conf):
"""
Provides quagga ospf6 functionality.
"""
template = Template("""\
$interfaces
!
router ospf6
router-id $routerid
$ospfifs
$redistribute
""")
def __init__(self, ospf6ifs, area, routerid, redistribute="! no redistribute"):
"""
Create a QuaggaOSPF6 instance.
:param list ospf6ifs: ospf6 interfaces
:param area: area
:param routerid: router id
:param str redistribute: redistribute value
"""
ospf6ifs = utils.make_tuple(ospf6ifs)
interfaces = "\n!\n".join(map(str, ospf6ifs))
ospfifs = "\n ".join(map(lambda x: "interface %s area %s" % (x.name(), area), ospf6ifs))
Conf.__init__(self, interfaces=interfaces, routerid=routerid, ospfifs=ospfifs, redistribute=redistribute)
class QuaggaConf(Conf):
"""
Provides quagga configuration functionality.
"""
template = Template("""\
log file $logfile
$debugs
!
$routers
!
$forwarding
""")
def __init__(self, routers, logfile, debugs=()):
"""
Create a QuaggaConf instance.
:param list routers: routers
:param str logfile: log file name
:param debugs: debug options
"""
routers = "\n!\n".join(map(str, utils.make_tuple(routers)))
if debugs:
debugs = "\n".join(utils.make_tuple(debugs))
else:
debugs = "! no debugs"
forwarding = "ip forwarding\nipv6 forwarding"
Conf.__init__(self, logfile=logfile, debugs=debugs, routers=routers, forwarding=forwarding)

View file

@ -1,739 +0,0 @@
"""
Definition of LxcNode, CoreNode, and other node classes that inherit from the CoreNode,
implementing specific node types.
"""
import logging
import socket
import threading
from socket import AF_INET
from socket import AF_INET6
from core import CoreCommandError
from core import constants
from core.coreobj import PyCoreNetIf
from core.coreobj import PyCoreNode
from core.coreobj import PyCoreObj
from core.data import LinkData
from core.enumerations import LinkTypes
from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs
from core.misc import ipaddress
from core.misc import utils
from core.netns.vnet import GreTapBridge
from core.netns.vnet import LxBrNet
from core.netns.vnode import LxcNode
class CtrlNet(LxBrNet):
"""
Control network functionality.
"""
policy = "ACCEPT"
# base control interface index
CTRLIF_IDX_BASE = 99
DEFAULT_PREFIX_LIST = [
"172.16.0.0/24 172.16.1.0/24 172.16.2.0/24 172.16.3.0/24 172.16.4.0/24",
"172.17.0.0/24 172.17.1.0/24 172.17.2.0/24 172.17.3.0/24 172.17.4.0/24",
"172.18.0.0/24 172.18.1.0/24 172.18.2.0/24 172.18.3.0/24 172.18.4.0/24",
"172.19.0.0/24 172.19.1.0/24 172.19.2.0/24 172.19.3.0/24 172.19.4.0/24"
]
def __init__(self, session, _id="ctrlnet", name=None, prefix=None,
hostid=None, start=True, assign_address=True,
updown_script=None, serverintf=None):
"""
Creates a CtrlNet instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node namee
:param prefix: control network ipv4 prefix
:param hostid: host id
:param bool start: start flag
:param str assign_address: assigned address
:param str updown_script: updown script
:param serverintf: server interface
:return:
"""
self.prefix = ipaddress.Ipv4Prefix(prefix)
self.hostid = hostid
self.assign_address = assign_address
self.updown_script = updown_script
self.serverintf = serverintf
LxBrNet.__init__(self, session, _id=_id, name=name, start=start)
def startup(self):
"""
Startup functionality for the control network.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.detectoldbridge():
return
LxBrNet.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)
logging.info("address %s", addr)
if self.updown_script:
logging.info("interface %s updown script (%s startup) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "startup"])
if self.serverintf:
# sets the interface as a port of the bridge
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf])
# bring interface up
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
def detectoldbridge(self):
"""
Occassionally, control net bridges from previously closed sessions are not cleaned up.
Check if there are old control net bridges and delete them
:return: True if an old bridge was detected, False otherwise
:rtype: bool
"""
status, output = utils.cmd_output([constants.BRCTL_BIN, "show"])
if status != 0:
logging.error("Unable to retrieve list of installed bridges")
else:
lines = output.split("\n")
for line in lines[1:]:
cols = line.split("\t")
oldbr = cols[0]
flds = cols[0].split(".")
if len(flds) == 3:
if flds[0] == "b" and flds[1] == self.id:
logging.error(
"error: An active control net bridge (%s) found. "
"An older session might still be running. "
"Stop all sessions and, if needed, delete %s to continue.", oldbr, oldbr
)
return True
return False
def shutdown(self):
"""
Control network shutdown.
:return: nothing
"""
if self.serverintf is not None:
try:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf])
except CoreCommandError:
logging.exception("error deleting server interface %s from bridge %s", self.serverintf, self.brname)
if self.updown_script is not None:
try:
logging.info("interface %s updown script (%s shutdown) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "shutdown"])
except CoreCommandError:
logging.exception("error issuing shutdown script shutdown")
LxBrNet.shutdown(self)
def all_link_data(self, flags):
"""
Do not include CtrlNet in link messages describing this session.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
return []
class CoreNode(LxcNode):
"""
Basic core node class for nodes to extend.
"""
apitype = NodeTypes.DEFAULT.value
class PtpNet(LxBrNet):
"""
Peer to peer network node.
"""
policy = "ACCEPT"
def attach(self, netif):
"""
Attach a network interface, but limit attachment to two interfaces.
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
if len(self._netif) >= 2:
raise ValueError("Point-to-point links support at most 2 network interfaces")
LxBrNet.attach(self, netif)
def data(self, message_type, lat=None, lon=None, alt=None):
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
:param message_type: purpose for the data object we are creating
:param float lat: latitude
:param float lon: longitude
:param float alt: altitude
:return: node data object
:rtype: core.data.NodeData
"""
return None
def all_link_data(self, flags):
"""
Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = []
if len(self._netif) != 2:
return all_links
if1, if2 = self._netif.values()
unidirectional = 0
if if1.getparams() != if2.getparams():
unidirectional = 1
interface1_ip4 = None
interface1_ip4_mask = None
interface1_ip6 = None
interface1_ip6_mask = None
for address in if1.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = AF_INET
ipl = socket.inet_pton(family, ip)
interface1_ip4 = ipaddress.IpAddress(af=family, address=ipl)
interface1_ip4_mask = mask
else:
family = AF_INET6
ipl = socket.inet_pton(family, ip)
interface1_ip6 = ipaddress.IpAddress(af=family, address=ipl)
interface1_ip6_mask = mask
interface2_ip4 = None
interface2_ip4_mask = None
interface2_ip6 = None
interface2_ip6_mask = None
for address in if2.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = AF_INET
ipl = socket.inet_pton(family, ip)
interface2_ip4 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip4_mask = mask
else:
family = AF_INET6
ipl = socket.inet_pton(family, ip)
interface2_ip6 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip6_mask = mask
link_data = LinkData(
message_type=flags,
node1_id=if1.node.id,
node2_id=if2.node.id,
link_type=self.linktype,
unidirectional=unidirectional,
delay=if1.getparam("delay"),
bandwidth=if1.getparam("bw"),
dup=if1.getparam("duplicate"),
jitter=if1.getparam("jitter"),
interface1_id=if1.node.getifindex(if1),
interface1_mac=if1.hwaddr,
interface1_ip4=interface1_ip4,
interface1_ip4_mask=interface1_ip4_mask,
interface1_ip6=interface1_ip6,
interface1_ip6_mask=interface1_ip6_mask,
interface2_id=if2.node.getifindex(if2),
interface2_mac=if2.hwaddr,
interface2_ip4=interface2_ip4,
interface2_ip4_mask=interface2_ip4_mask,
interface2_ip6=interface2_ip6,
interface2_ip6_mask=interface2_ip6_mask,
)
all_links.append(link_data)
# build a 2nd link message for the upstream link parameters
# (swap if1 and if2)
if unidirectional:
link_data = LinkData(
message_type=0,
node1_id=if2.node.id,
node2_id=if1.node.id,
delay=if1.getparam("delay"),
bandwidth=if1.getparam("bw"),
dup=if1.getparam("duplicate"),
jitter=if1.getparam("jitter"),
unidirectional=1,
interface1_id=if2.node.getifindex(if2),
interface2_id=if1.node.getifindex(if1)
)
all_links.append(link_data)
return all_links
class SwitchNode(LxBrNet):
"""
Provides switch functionality within a core node.
"""
apitype = NodeTypes.SWITCH.value
policy = "ACCEPT"
type = "lanswitch"
class HubNode(LxBrNet):
"""
Provides hub functionality within a core node, forwards packets to all bridge
ports by turning off MAC address learning.
"""
apitype = NodeTypes.HUB.value
policy = "ACCEPT"
type = "hub"
def __init__(self, session, _id=None, name=None, start=True):
"""
Creates a HubNode instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node namee
:param bool start: start flag
:raises CoreCommandError: when there is a command exception
"""
LxBrNet.__init__(self, session, _id, name, start)
# TODO: move to startup method
if start:
utils.check_cmd([constants.BRCTL_BIN, "setageing", self.brname, "0"])
class WlanNode(LxBrNet):
"""
Provides wireless lan functionality within a core node.
"""
apitype = NodeTypes.WIRELESS_LAN.value
linktype = LinkTypes.WIRELESS.value
policy = "DROP"
type = "wlan"
def __init__(self, session, _id=None, name=None, start=True, policy=None):
"""
Create a WlanNode instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node name
:param bool start: start flag
:param policy: wlan policy
"""
LxBrNet.__init__(self, session, _id, name, start, policy)
# wireless model such as basic range
self.model = None
# mobility model such as scripted
self.mobility = None
def attach(self, netif):
"""
Attach a network interface.
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
LxBrNet.attach(self, netif)
if self.model:
netif.poshook = self.model.position_callback
if netif.node is None:
return
x, y, z = netif.node.position.get()
# invokes any netif.poshook
netif.setposition(x, y, z)
def setmodel(self, model, config):
"""
Sets the mobility and wireless model.
:param core.mobility.WirelessModel.cls model: wireless model to set to
:param dict config: configuration for model being set
:return: nothing
"""
logging.info("adding model: %s", model.name)
if model.config_type == RegisterTlvs.WIRELESS.value:
self.model = model(session=self.session, object_id=self.id)
self.model.update_config(config)
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.setlinkparams()
elif model.config_type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, object_id=self.id)
self.mobility.update_config(config)
def update_mobility(self, config):
if not self.mobility:
raise ValueError("no mobility set to update for node(%s)", self.id)
self.mobility.set_configs(config, node_id=self.id)
def updatemodel(self, config):
if not self.model:
raise ValueError("no model set to update for node(%s)", self.id)
logging.info("node(%s) updating model(%s): %s", self.id, self.model.name, config)
self.model.set_configs(config, node_id=self.id)
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.updateconfig()
def all_link_data(self, flags):
"""
Retrieve all link data.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = LxBrNet.all_link_data(self, flags)
if self.model:
all_links.extend(self.model.all_link_data(flags))
return all_links
class RJ45Node(PyCoreNode, PyCoreNetIf):
"""
RJ45Node is a physical interface on the host linked to the emulated
network.
"""
apitype = NodeTypes.RJ45.value
type = "rj45"
def __init__(self, session, _id=None, name=None, mtu=1500, start=True):
"""
Create an RJ45Node instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node name
:param mtu: rj45 mtu
:param bool start: start flag
:return:
"""
PyCoreNode.__init__(self, session, _id, name, start=start)
PyCoreNetIf.__init__(self, node=self, name=name, mtu=mtu)
self.up = False
self.lock = threading.RLock()
self.ifindex = None
# the following are PyCoreNetIf attributes
self.transport_type = "raw"
self.localname = name
self.old_up = False
self.old_addrs = []
if start:
self.startup()
def startup(self):
"""
Set the interface in the up state.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
# interface will also be marked up during net.attach()
self.savestate()
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
self.up = True
def shutdown(self):
"""
Bring the interface down. Remove any addresses and queuing
disciplines.
:return: nothing
"""
if not self.up:
return
try:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"])
utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname])
utils.check_cmd([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"])
except CoreCommandError:
logging.exception("error shutting down")
self.up = False
self.restorestate()
# TODO: issue in that both classes inherited from provide the same method with different signatures
def attachnet(self, net):
"""
Attach a network.
:param core.coreobj.PyCoreNet net: network to attach
:return: nothing
"""
PyCoreNetIf.attachnet(self, net)
# TODO: issue in that both classes inherited from provide the same method with different signatures
def detachnet(self):
"""
Detach a network.
:return: nothing
"""
PyCoreNetIf.detachnet(self)
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
"""
This is called when linking with another node. Since this node
represents an interface, we do not create another object here,
but attach ourselves to the given network.
:param core.coreobj.PyCoreNet net: new network instance
:param list[str] addrlist: address list
:param str hwaddr: hardware address
:param int ifindex: interface index
:param str ifname: interface name
:return: interface index
:rtype: int
:raises ValueError: when an interface has already been created, one max
"""
with self.lock:
if ifindex is None:
ifindex = 0
if self.net is not None:
raise ValueError("RJ45 nodes support at most 1 network interface")
self._netif[ifindex] = self
# PyCoreNetIf.node is self
self.node = self
self.ifindex = ifindex
if net is not None:
self.attachnet(net)
if addrlist:
for addr in utils.make_tuple(addrlist):
self.addaddr(addr)
return ifindex
def delnetif(self, ifindex):
"""
Delete a network interface.
:param int ifindex: interface index to delete
:return: nothing
"""
if ifindex is None:
ifindex = 0
self._netif.pop(ifindex)
if ifindex == self.ifindex:
self.shutdown()
else:
raise ValueError("ifindex %s does not exist" % ifindex)
def netif(self, ifindex, net=None):
"""
This object is considered the network interface, so we only
return self here. This keeps the RJ45Node compatible with
real nodes.
:param int ifindex: interface index to retrieve
:param net: network to retrieve
:return: a network interface
:rtype: core.coreobj.PyCoreNetIf
"""
if net is not None and net == self.net:
return self
if ifindex is None:
ifindex = 0
if ifindex == self.ifindex:
return self
return None
def getifindex(self, netif):
"""
Retrieve network interface index.
:param core.coreobj.PyCoreNetIf netif: network interface to retrieve index for
:return: interface index, None otherwise
:rtype: int
"""
if netif != self:
return None
return self.ifindex
def addaddr(self, addr):
"""
Add address to to network interface.
:param str addr: address to add
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
PyCoreNetIf.addaddr(self, addr)
def deladdr(self, addr):
"""
Delete address from network interface.
:param str addr: address to delete
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name])
PyCoreNetIf.deladdr(self, addr)
def savestate(self):
"""
Save the addresses and other interface state before using the
interface for emulation purposes. TODO: save/restore the PROMISC flag
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
self.old_up = False
self.old_addrs = []
args = [constants.IP_BIN, "addr", "show", "dev", self.localname]
output = utils.check_cmd(args)
for line in output.split("\n"):
items = line.split()
if len(items) < 2:
continue
if items[1] == "%s:" % self.localname:
flags = items[2][1:-1].split(",")
if "UP" in flags:
self.old_up = True
elif items[0] == "inet":
self.old_addrs.append((items[1], items[3]))
elif items[0] == "inet6":
if items[1][:4] == "fe80":
continue
self.old_addrs.append((items[1], None))
def restorestate(self):
"""
Restore the addresses and other interface state after using it.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
for addr in self.old_addrs:
if addr[1] is None:
utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "dev", self.localname])
else:
utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "brd", addr[1], "dev", self.localname])
if self.old_up:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
def setposition(self, x=None, y=None, z=None):
"""
Uses setposition from both parent classes.
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
result = PyCoreObj.setposition(self, x, y, z)
PyCoreNetIf.setposition(self, x, y, z)
return result
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: exist status and combined stdout and stderr
:rtype: tuple[int, str]
:raises CoreCommandError: when a non-zero exit status occurs
"""
raise NotImplementedError
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
raise NotImplementedError
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
raise NotImplementedError
def termcmdstring(self, sh):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
raise NotImplementedError
class TunnelNode(GreTapBridge):
"""
Provides tunnel functionality in a core node.
"""
apitype = NodeTypes.TUNNEL.value
policy = "ACCEPT"
type = "tunnel"

View file

@ -1,609 +0,0 @@
"""
PyCoreNode and LxcNode classes that implement the network namespac virtual node.
"""
import errno
import logging
import os
import random
import shutil
import signal
import string
import threading
from core import CoreCommandError
from core import constants
from core.coreobj import PyCoreNetIf
from core.coreobj import PyCoreNode
from core.enumerations import NodeTypes
from core.misc import nodeutils
from core.misc import utils
from core.misc.ipaddress import MacAddress
from core.netns import vnodeclient
from core.netns.vif import TunTap
from core.netns.vif import VEth
_DEFAULT_MTU = 1500
utils.check_executables([constants.IP_BIN])
class SimpleLxcNode(PyCoreNode):
"""
Provides simple lxc functionality for core nodes.
:var nodedir: str
:var ctrlchnlname: str
:var client: core.netns.vnodeclient.VnodeClient
:var pid: int
:var up: bool
:var lock: threading.RLock
:var _mounts: list[tuple[str, str]]
"""
valid_address_types = {"inet", "inet6", "inet6link"}
def __init__(self, session, _id=None, name=None, nodedir=None, start=True):
"""
Create a SimpleLxcNode instance.
:param core.session.Session session: core session instance
:param int _id: object id
:param str name: object name
:param str nodedir: node directory
:param bool start: start flag
"""
PyCoreNode.__init__(self, session, _id, name, start=start)
self.nodedir = nodedir
self.ctrlchnlname = os.path.abspath(os.path.join(self.session.session_dir, self.name))
self.client = None
self.pid = None
self.up = False
self.lock = threading.RLock()
self._mounts = []
def alive(self):
"""
Check if the node is alive.
:return: True if node is alive, False otherwise
:rtype: bool
"""
try:
os.kill(self.pid, 0)
except OSError:
return False
return True
def startup(self):
"""
Start a new namespace node by invoking the vnoded process that
allocates a new namespace. Bring up the loopback device and set
the hostname.
:return: nothing
"""
if self.up:
raise ValueError("starting a node that is already up")
# create a new namespace for this node using vnoded
vnoded = [
constants.VNODED_BIN,
"-v",
"-c", self.ctrlchnlname,
"-l", self.ctrlchnlname + ".log",
"-p", self.ctrlchnlname + ".pid"
]
if self.nodedir:
vnoded += ["-C", self.nodedir]
env = self.session.get_environment(state=False)
env["NODE_NUMBER"] = str(self.id)
env["NODE_NAME"] = str(self.name)
output = utils.check_cmd(vnoded, env=env)
self.pid = int(output)
# create vnode client
self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname)
# bring up the loopback interface
logging.debug("bringing up loopback interface")
self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"])
# set hostname for node
logging.debug("setting hostname: %s", self.name)
self.check_cmd(["hostname", self.name])
# mark node as up
self.up = True
def shutdown(self):
"""
Shutdown logic for simple lxc nodes.
:return: nothing
"""
# nothing to do if node is not up
if not self.up:
return
# unmount all targets (NOTE: non-persistent mount namespaces are
# removed by the kernel when last referencing process is killed)
self._mounts = []
# shutdown all interfaces
for netif in self.netifs():
netif.shutdown()
# attempt to kill node process and wait for termination of children
try:
os.kill(self.pid, signal.SIGTERM)
os.waitpid(self.pid, 0)
except OSError as e:
if e.errno != 10:
logging.exception("error killing process")
# remove node directory if present
try:
os.unlink(self.ctrlchnlname)
except OSError as e:
# no such file or directory
if e.errno != errno.ENOENT:
logging.exception("error removing node directory")
# clear interface data, close client, and mark self and not up
self._netif.clear()
self.client.close()
self.up = False
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
return self.client.cmd(args, wait)
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
return self.client.cmd_output(args)
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
return self.client.check_cmd(args)
def termcmdstring(self, sh="/bin/sh"):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
return self.client.termcmdstring(sh)
def mount(self, source, target):
"""
Create and mount a directory.
:param str source: source directory to mount
:param str target: target directory to create
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
source = os.path.abspath(source)
logging.info("node(%s) mounting: %s at %s", self.name, source, target)
cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target)
status, output = self.client.shcmd_result(cmd)
if status:
raise CoreCommandError(status, cmd, output)
self._mounts.append((source, target))
def newifindex(self):
"""
Retrieve a new interface index.
:return: new interface index
:rtype: int
"""
with self.lock:
return super(SimpleLxcNode, self).newifindex()
def newveth(self, ifindex=None, ifname=None, net=None):
"""
Create a new interface.
:param int ifindex: index for the new interface
:param str ifname: name for the new interface
:param net: network to associate interface with
:return: nothing
"""
with self.lock:
if ifindex is None:
ifindex = self.newifindex()
if ifname is None:
ifname = "eth%d" % ifindex
sessionid = self.session.short_session_id()
try:
suffix = "%x.%s.%s" % (self.id, ifindex, sessionid)
except TypeError:
suffix = "%s.%s.%s" % (self.id, ifindex, sessionid)
localname = "veth" + suffix
if len(localname) >= 16:
raise ValueError("interface local name (%s) too long" % localname)
name = localname + "p"
if len(name) >= 16:
raise ValueError("interface name (%s) too long" % name)
veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up)
if self.up:
utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])
veth.name = ifname
if self.up:
# TODO: potentially find better way to query interface ID
# retrieve interface information
output = self.check_cmd(["ip", "link", "show", veth.name])
logging.debug("interface command output: %s", output)
output = output.split("\n")
veth.flow_id = int(output[0].strip().split(":")[0]) + 1
logging.debug("interface flow index: %s - %s", veth.name, veth.flow_id)
veth.hwaddr = MacAddress.from_string(output[1].strip().split()[1])
logging.debug("interface mac: %s - %s", veth.name, veth.hwaddr)
try:
self.addnetif(veth, ifindex)
except ValueError as e:
veth.shutdown()
del veth
raise e
return ifindex
def newtuntap(self, ifindex=None, ifname=None, net=None):
"""
Create a new tunnel tap.
:param int ifindex: interface index
:param str ifname: interface name
:param net: network to associate with
:return: interface index
:rtype: int
"""
with self.lock:
if ifindex is None:
ifindex = self.newifindex()
if ifname is None:
ifname = "eth%d" % ifindex
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, net=net, start=self.up)
try:
self.addnetif(tuntap, ifindex)
except ValueError as e:
tuntap.shutdown()
del tuntap
raise e
return ifindex
def sethwaddr(self, ifindex, addr):
"""
Set hardware addres for an interface.
:param int ifindex: index of interface to set hardware address for
:param core.misc.ipaddress.MacAddress addr: hardware address to set
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
self._netif[ifindex].sethwaddr(addr)
if self.up:
args = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)]
self.check_cmd(args)
def addaddr(self, ifindex, addr):
"""
Add interface address.
:param int ifindex: index of interface to add address to
:param str addr: address to add to interface
:return: nothing
"""
if self.up:
# check if addr is ipv6
if ":" in str(addr):
args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]
self.check_cmd(args)
else:
args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)]
self.check_cmd(args)
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
"""
Delete address from an interface.
:param int ifindex: index of interface to delete address from
:param str addr: address to delete from interface
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
try:
self._netif[ifindex].deladdr(addr)
except ValueError:
logging.exception("trying to delete unknown address: %s" % addr)
if self.up:
self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
def delalladdr(self, ifindex, address_types=None):
"""
Delete all addresses from an interface.
:param int ifindex: index of interface to delete address types from
:param tuple[str] address_types: address types to delete
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
if not address_types:
address_types = self.valid_address_types
interface_name = self.ifname(ifindex)
addresses = self.client.getaddr(interface_name, rescan=True)
for address_type in address_types:
if address_type not in self.valid_address_types:
raise ValueError("addr type must be in: %s" % " ".join(self.valid_address_types))
for address in addresses[address_type]:
self.deladdr(ifindex, address)
# update cached information
self.client.getaddr(interface_name, rescan=True)
def ifup(self, ifindex):
"""
Bring an interface up.
:param int ifindex: index of interface to bring up
:return: nothing
"""
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"])
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
"""
Create a new network interface.
:param net: network to associate with
:param list addrlist: addresses to add on the interface
:param core.misc.ipaddress.MacAddress hwaddr: hardware address to set for interface
:param int ifindex: index of interface to create
:param str ifname: name for interface
:return: interface index
:rtype: int
"""
if not addrlist:
addrlist = []
with self.lock:
# TODO: see if you can move this to emane specific code
if nodeutils.is_node(net, NodeTypes.EMANE):
ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net)
# TUN/TAP is not ready for addressing yet; the device may
# take some time to appear, and installing it into a
# namespace after it has been bound removes addressing;
# save addresses with the interface now
self.attachnet(ifindex, net)
netif = self.netif(ifindex)
netif.sethwaddr(hwaddr)
for address in utils.make_tuple(addrlist):
netif.addaddr(address)
return ifindex
else:
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
if net is not None:
self.attachnet(ifindex, net)
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
for address in utils.make_tuple(addrlist):
self.addaddr(ifindex, address)
self.ifup(ifindex)
return ifindex
def connectnode(self, ifname, othernode, otherifname):
"""
Connect a node.
:param str ifname: name of interface to connect
:param core.netns.nodes.LxcNode 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 xrange(tmplen)])
tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)])
utils.check_cmd([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2])
utils.check_cmd([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)])
self.check_cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname])
interface = PyCoreNetIf(node=self, name=ifname, mtu=_DEFAULT_MTU)
self.addnetif(interface, self.newifindex())
utils.check_cmd([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)])
othernode.check_cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname])
other_interface = PyCoreNetIf(node=othernode, name=otherifname, mtu=_DEFAULT_MTU)
othernode.addnetif(other_interface, othernode.newifindex())
def addfile(self, srcname, filename):
"""
Add a file.
:param str srcname: source file name
:param str filename: file name to add
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
logging.info("adding file from %s to %s", srcname, filename)
directory = os.path.dirname(filename)
cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename)
status, output = self.client.shcmd_result(cmd)
if status:
raise CoreCommandError(status, cmd, output)
class LxcNode(SimpleLxcNode):
"""
Provides lcx node functionality for core nodes.
"""
def __init__(self, session, _id=None, name=None, nodedir=None, bootsh="boot.sh", start=True):
"""
Create a LxcNode instance.
:param core.session.Session session: core session instance
:param int _id: object id
:param str name: object name
:param str nodedir: node directory
:param bootsh: boot shell
:param bool start: start flag
"""
super(LxcNode, self).__init__(session=session, _id=_id, name=name, nodedir=nodedir, start=start)
self.bootsh = bootsh
if start:
self.startup()
def startup(self):
"""
Startup logic for the node.
:return: nothing
"""
with self.lock:
self.makenodedir()
super(LxcNode, self).startup()
self.privatedir("/var/run")
self.privatedir("/var/log")
def shutdown(self):
"""
Shutdown logic for the node.
:return: nothing
"""
if not self.up:
return
with self.lock:
try:
super(LxcNode, self).shutdown()
except OSError:
logging.exception("error during shutdown")
finally:
self.rmnodedir()
def privatedir(self, path):
"""
Create a private directory.
:param str path: path to create
:return: nothing
"""
if path[0] != "/":
raise ValueError("path not fully qualified: %s" % path)
hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip("/").replace("/", "."))
os.mkdir(hostpath)
self.mount(hostpath, path)
def hostfilename(self, filename):
"""
Return the name of a node"s file on the host filesystem.
:param str filename: host file name
:return: path to file
"""
dirname, basename = os.path.split(filename)
if not basename:
raise ValueError("no basename for filename: %s" % filename)
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")
dirname = os.path.join(self.nodedir, dirname)
return os.path.join(dirname, basename)
def opennodefile(self, filename, mode="w"):
"""
Open a node file, within it"s directory.
:param str filename: file name to open
:param str mode: mode to open file in
:return: open file
:rtype: file
"""
hostfilename = self.hostfilename(filename)
dirname, _basename = os.path.split(hostfilename)
if not os.path.isdir(dirname):
os.makedirs(dirname, mode=0755)
return open(hostfilename, mode)
def nodefile(self, filename, contents, mode=0644):
"""
Create a node file with a given mode.
:param str filename: name of file to create
:param contents: contents of file
:param int mode: mode for file
:return: nothing
"""
with self.opennodefile(filename, "w") as open_file:
open_file.write(contents)
os.chmod(open_file.name, mode)
logging.info("node(%s) added file: %s; mode: 0%o", self.name, open_file.name, mode)
def nodefilecopy(self, filename, srcfilename, mode=None):
"""
Copy a file to a node, following symlinks and preserving metadata.
Change file mode if specified.
:param str filename: file name to copy file to
:param str srcfilename: file to copy
:param int mode: mode to copy to
:return: nothing
"""
hostfilename = self.hostfilename(filename)
shutil.copy2(srcfilename, hostfilename)
if mode is not None:
os.chmod(hostfilename, mode)
logging.info("node(%s) copied file: %s; mode: %s", self.name, hostfilename, mode)

1158
daemon/core/nodes/base.py Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
""" """
vnodeclient.py: implementation of the VnodeClient class for issuing commands client.py: implementation of the VnodeClient class for issuing commands
over a control channel to the vnoded process running in a network namespace. over a control channel to the vnoded process running in a network namespace.
The control channel can be accessed via calls to the vcmd Python module or The control channel can be accessed via calls to the vcmd Python module or
by invoking the vcmd shell command. by invoking the vcmd shell command.
@ -10,9 +10,8 @@ import os
import vcmd import vcmd
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.misc import utils
class VnodeClient(object): class VnodeClient(object):

View file

@ -5,17 +5,175 @@ virtual ethernet classes that implement the interfaces available under Linux.
import logging import logging
import time import time
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.coreobj import PyCoreNetIf from core.emulator.enumerations import NodeTypes
from core.enumerations import NodeTypes from core.nodes import nodeutils
from core.misc import nodeutils
from core.misc import utils
utils.check_executables([constants.IP_BIN]) utils.check_executables([constants.IP_BIN])
class VEth(PyCoreNetIf): class CoreInterface(object):
"""
Base class for network interfaces.
"""
def __init__(self, node, name, mtu):
"""
Creates a PyCoreNetIf instance.
:param core.coreobj.PyCoreNode node: node for interface
:param str name: interface name
:param mtu: mtu value
"""
self.node = node
self.name = name
if not isinstance(mtu, (int, long)):
raise ValueError
self.mtu = mtu
self.net = None
self._params = {}
self.addrlist = []
self.hwaddr = None
# placeholder position hook
self.poshook = lambda a, b, c, d: None
# used with EMANE
self.transport_type = None
# interface index on the network
self.netindex = None
# index used to find flow data
self.flow_id = None
def startup(self):
"""
Startup method for the interface.
:return: nothing
"""
pass
def shutdown(self):
"""
Shutdown method for the interface.
:return: nothing
"""
pass
def attachnet(self, net):
"""
Attach network.
:param core.coreobj.PyCoreNet net: network to attach
:return: nothing
"""
if self.net:
self.detachnet()
self.net = None
net.attach(self)
self.net = net
def detachnet(self):
"""
Detach from a network.
:return: nothing
"""
if self.net is not None:
self.net.detach(self)
def addaddr(self, addr):
"""
Add address.
:param str addr: address to add
:return: nothing
"""
self.addrlist.append(addr)
def deladdr(self, addr):
"""
Delete address.
:param str addr: address to delete
:return: nothing
"""
self.addrlist.remove(addr)
def sethwaddr(self, addr):
"""
Set hardware address.
:param core.misc.ipaddress.MacAddress addr: hardware address to set to.
:return: nothing
"""
self.hwaddr = addr
def getparam(self, key):
"""
Retrieve a parameter from the, or None if the parameter does not exist.
:param key: parameter to get value for
:return: parameter value
"""
return self._params.get(key)
def getparams(self):
"""
Return (key, value) pairs for parameters.
"""
parameters = []
for k in sorted(self._params.keys()):
parameters.append((k, self._params[k]))
return parameters
def setparam(self, key, value):
"""
Set a parameter value, returns True if the parameter has changed.
:param key: parameter name to set
:param value: parameter value
:return: True if parameter changed, False otherwise
"""
# treat None and 0 as unchanged values
current_value = self._params.get(key)
if current_value == value or current_value <= 0 and value <= 0:
return False
self._params[key] = value
return True
def swapparams(self, name):
"""
Swap out parameters dict for name. If name does not exist,
intialize it. This is for supporting separate upstream/downstream
parameters when two layer-2 nodes are linked together.
:param str name: name of parameter to swap
:return: nothing
"""
tmp = self._params
if not hasattr(self, name):
setattr(self, name, {})
self._params = getattr(self, name)
setattr(self, name, tmp)
def setposition(self, x, y, z):
"""
Dispatch position hook handler.
:param x: x position
:param y: y position
:param z: z position
:return: nothing
"""
self.poshook(self, x, y, z)
class Veth(CoreInterface):
""" """
Provides virtual ethernet functionality for core nodes. Provides virtual ethernet functionality for core nodes.
""" """
@ -34,7 +192,7 @@ class VEth(PyCoreNetIf):
:raises CoreCommandError: when there is a command exception :raises CoreCommandError: when there is a command exception
""" """
# note that net arg is ignored # note that net arg is ignored
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) CoreInterface.__init__(self, node=node, name=name, mtu=mtu)
self.localname = localname self.localname = localname
self.up = False self.up = False
if start: if start:
@ -76,7 +234,7 @@ class VEth(PyCoreNetIf):
self.up = False self.up = False
class TunTap(PyCoreNetIf): class TunTap(CoreInterface):
""" """
TUN/TAP virtual device in TAP mode TUN/TAP virtual device in TAP mode
""" """
@ -93,7 +251,7 @@ class TunTap(PyCoreNetIf):
:param net: related network :param net: related network
:param bool start: start flag :param bool start: start flag
""" """
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) CoreInterface.__init__(self, node=node, name=name, mtu=mtu)
self.localname = localname self.localname = localname
self.up = False self.up = False
self.transport_type = "virtual" self.transport_type = "virtual"
@ -233,7 +391,7 @@ class TunTap(PyCoreNetIf):
self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
class GreTap(PyCoreNetIf): class GreTap(CoreInterface):
""" """
GRE TAP device for tunneling between emulation servers. GRE TAP device for tunneling between emulation servers.
Uses the "gretap" tunnel device type from Linux which is a GRE device Uses the "gretap" tunnel device type from Linux which is a GRE device
@ -258,7 +416,7 @@ class GreTap(PyCoreNetIf):
:param bool start: start flag :param bool start: start flag
:raises CoreCommandError: when there is a command exception :raises CoreCommandError: when there is a command exception
""" """
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) CoreInterface.__init__(self, node=node, name=name, mtu=mtu)
self.session = session self.session = session
if _id is None: if _id is None:
# from PyCoreObj # from PyCoreObj

View file

@ -5,15 +5,19 @@ Linux Ethernet bridging and ebtables rules.
import logging import logging
import os import os
import socket
import threading import threading
import time import time
from socket import AF_INET, AF_INET6
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.coreobj import PyCoreNet from core.nodes.base import CoreNetworkBase
from core.misc import utils from core.emulator.data import LinkData
from core.netns.vif import GreTap from core.emulator.enumerations import NodeTypes, LinkTypes, RegisterTlvs
from core.netns.vif import VEth from core.nodes import ipaddress
from core.nodes.interface import GreTap
from core.nodes.interface import Veth
utils.check_executables([ utils.check_executables([
constants.BRCTL_BIN, constants.BRCTL_BIN,
@ -236,9 +240,9 @@ def ebtablescmds(call, cmds):
call(args) call(args)
class LxBrNet(PyCoreNet): class CoreNetwork(CoreNetworkBase):
""" """
Provides linux bridge network functionlity for core nodes. Provides linux bridge network functionality for core nodes.
""" """
policy = "DROP" policy = "DROP"
@ -252,7 +256,7 @@ class LxBrNet(PyCoreNet):
:param bool start: start flag :param bool start: start flag
:param policy: network policy :param policy: network policy
""" """
PyCoreNet.__init__(self, session, _id, name, start) CoreNetworkBase.__init__(self, session, _id, name, start)
if name is None: if name is None:
name = str(self.id) name = str(self.id)
if policy is not None: if policy is not None:
@ -333,7 +337,7 @@ class LxBrNet(PyCoreNet):
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname]) utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"]) utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"])
PyCoreNet.attach(self, netif) CoreNetworkBase.attach(self, netif)
def detach(self, netif): def detach(self, netif):
""" """
@ -345,7 +349,7 @@ class LxBrNet(PyCoreNet):
if self.up: if self.up:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname]) utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname])
PyCoreNet.detach(self, netif) CoreNetworkBase.detach(self, netif)
def linked(self, netif1, netif2): def linked(self, netif1, netif2):
""" """
@ -520,7 +524,7 @@ class LxBrNet(PyCoreNet):
if len(name) >= 16: if len(name) >= 16:
raise ValueError("interface name %s too long" % name) raise ValueError("interface name %s too long" % name)
netif = VEth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up) netif = Veth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up)
self.attach(netif) self.attach(netif)
if net.up: if net.up:
# this is similar to net.attach() but uses netif.name instead # this is similar to net.attach() but uses netif.name instead
@ -564,7 +568,7 @@ class LxBrNet(PyCoreNet):
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname]) utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname])
class GreTapBridge(LxBrNet): class GreTapBridge(CoreNetwork):
""" """
A network consisting of a bridge with a gretap device for tunneling to A network consisting of a bridge with a gretap device for tunneling to
another system. another system.
@ -586,7 +590,7 @@ class GreTapBridge(LxBrNet):
:param bool start: start flag :param bool start: start flag
:return: :return:
""" """
LxBrNet.__init__(self, session=session, _id=_id, name=name, policy=policy, start=False) CoreNetwork.__init__(self, session=session, _id=_id, name=name, policy=policy, start=False)
self.grekey = key self.grekey = key
if self.grekey is None: if self.grekey is None:
self.grekey = self.session.id ^ self.id self.grekey = self.session.id ^ self.id
@ -609,7 +613,7 @@ class GreTapBridge(LxBrNet):
:return: nothing :return: nothing
""" """
LxBrNet.startup(self) CoreNetwork.startup(self)
if self.gretap: if self.gretap:
self.attach(self.gretap) self.attach(self.gretap)
@ -623,7 +627,7 @@ class GreTapBridge(LxBrNet):
self.detach(self.gretap) self.detach(self.gretap)
self.gretap.shutdown() self.gretap.shutdown()
self.gretap = None self.gretap = None
LxBrNet.shutdown(self) CoreNetwork.shutdown(self)
def addrconfig(self, addrlist): def addrconfig(self, addrlist):
""" """
@ -654,3 +658,412 @@ class GreTapBridge(LxBrNet):
:return: nothing :return: nothing
""" """
self.grekey = key self.grekey = key
class CtrlNet(CoreNetwork):
"""
Control network functionality.
"""
policy = "ACCEPT"
# base control interface index
CTRLIF_IDX_BASE = 99
DEFAULT_PREFIX_LIST = [
"172.16.0.0/24 172.16.1.0/24 172.16.2.0/24 172.16.3.0/24 172.16.4.0/24",
"172.17.0.0/24 172.17.1.0/24 172.17.2.0/24 172.17.3.0/24 172.17.4.0/24",
"172.18.0.0/24 172.18.1.0/24 172.18.2.0/24 172.18.3.0/24 172.18.4.0/24",
"172.19.0.0/24 172.19.1.0/24 172.19.2.0/24 172.19.3.0/24 172.19.4.0/24"
]
def __init__(self, session, _id="ctrlnet", name=None, prefix=None,
hostid=None, start=True, assign_address=True,
updown_script=None, serverintf=None):
"""
Creates a CtrlNet instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node namee
:param prefix: control network ipv4 prefix
:param hostid: host id
:param bool start: start flag
:param str assign_address: assigned address
:param str updown_script: updown script
:param serverintf: server interface
:return:
"""
self.prefix = ipaddress.Ipv4Prefix(prefix)
self.hostid = hostid
self.assign_address = assign_address
self.updown_script = updown_script
self.serverintf = serverintf
CoreNetwork.__init__(self, session, _id=_id, name=name, start=start)
def startup(self):
"""
Startup functionality for the control network.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.detectoldbridge():
return
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)
logging.info("address %s", addr)
if self.updown_script:
logging.info("interface %s updown script (%s startup) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "startup"])
if self.serverintf:
# sets the interface as a port of the bridge
utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf])
# bring interface up
utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"])
def detectoldbridge(self):
"""
Occassionally, control net bridges from previously closed sessions are not cleaned up.
Check if there are old control net bridges and delete them
:return: True if an old bridge was detected, False otherwise
:rtype: bool
"""
status, output = utils.cmd_output([constants.BRCTL_BIN, "show"])
if status != 0:
logging.error("Unable to retrieve list of installed bridges")
else:
lines = output.split("\n")
for line in lines[1:]:
cols = line.split("\t")
oldbr = cols[0]
flds = cols[0].split(".")
if len(flds) == 3:
if flds[0] == "b" and flds[1] == self.id:
logging.error(
"error: An active control net bridge (%s) found. "
"An older session might still be running. "
"Stop all sessions and, if needed, delete %s to continue.", oldbr, oldbr
)
return True
return False
def shutdown(self):
"""
Control network shutdown.
:return: nothing
"""
if self.serverintf is not None:
try:
utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf])
except CoreCommandError:
logging.exception("error deleting server interface %s from bridge %s", self.serverintf, self.brname)
if self.updown_script is not None:
try:
logging.info("interface %s updown script (%s shutdown) called", self.brname, self.updown_script)
utils.check_cmd([self.updown_script, self.brname, "shutdown"])
except CoreCommandError:
logging.exception("error issuing shutdown script shutdown")
CoreNetwork.shutdown(self)
def all_link_data(self, flags):
"""
Do not include CtrlNet in link messages describing this session.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
return []
class PtpNet(CoreNetwork):
"""
Peer to peer network node.
"""
policy = "ACCEPT"
def attach(self, netif):
"""
Attach a network interface, but limit attachment to two interfaces.
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
if len(self._netif) >= 2:
raise ValueError("Point-to-point links support at most 2 network interfaces")
CoreNetwork.attach(self, netif)
def data(self, message_type, lat=None, lon=None, alt=None):
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
:param message_type: purpose for the data object we are creating
:param float lat: latitude
:param float lon: longitude
:param float alt: altitude
:return: node data object
:rtype: core.data.NodeData
"""
return None
def all_link_data(self, flags):
"""
Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = []
if len(self._netif) != 2:
return all_links
if1, if2 = self._netif.values()
unidirectional = 0
if if1.getparams() != if2.getparams():
unidirectional = 1
interface1_ip4 = None
interface1_ip4_mask = None
interface1_ip6 = None
interface1_ip6_mask = None
for address in if1.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = AF_INET
ipl = socket.inet_pton(family, ip)
interface1_ip4 = ipaddress.IpAddress(af=family, address=ipl)
interface1_ip4_mask = mask
else:
family = AF_INET6
ipl = socket.inet_pton(family, ip)
interface1_ip6 = ipaddress.IpAddress(af=family, address=ipl)
interface1_ip6_mask = mask
interface2_ip4 = None
interface2_ip4_mask = None
interface2_ip6 = None
interface2_ip6_mask = None
for address in if2.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = AF_INET
ipl = socket.inet_pton(family, ip)
interface2_ip4 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip4_mask = mask
else:
family = AF_INET6
ipl = socket.inet_pton(family, ip)
interface2_ip6 = ipaddress.IpAddress(af=family, address=ipl)
interface2_ip6_mask = mask
link_data = LinkData(
message_type=flags,
node1_id=if1.node.id,
node2_id=if2.node.id,
link_type=self.linktype,
unidirectional=unidirectional,
delay=if1.getparam("delay"),
bandwidth=if1.getparam("bw"),
dup=if1.getparam("duplicate"),
jitter=if1.getparam("jitter"),
interface1_id=if1.node.getifindex(if1),
interface1_mac=if1.hwaddr,
interface1_ip4=interface1_ip4,
interface1_ip4_mask=interface1_ip4_mask,
interface1_ip6=interface1_ip6,
interface1_ip6_mask=interface1_ip6_mask,
interface2_id=if2.node.getifindex(if2),
interface2_mac=if2.hwaddr,
interface2_ip4=interface2_ip4,
interface2_ip4_mask=interface2_ip4_mask,
interface2_ip6=interface2_ip6,
interface2_ip6_mask=interface2_ip6_mask,
)
all_links.append(link_data)
# build a 2nd link message for the upstream link parameters
# (swap if1 and if2)
if unidirectional:
link_data = LinkData(
message_type=0,
node1_id=if2.node.id,
node2_id=if1.node.id,
delay=if1.getparam("delay"),
bandwidth=if1.getparam("bw"),
dup=if1.getparam("duplicate"),
jitter=if1.getparam("jitter"),
unidirectional=1,
interface1_id=if2.node.getifindex(if2),
interface2_id=if1.node.getifindex(if1)
)
all_links.append(link_data)
return all_links
class SwitchNode(CoreNetwork):
"""
Provides switch functionality within a core node.
"""
apitype = NodeTypes.SWITCH.value
policy = "ACCEPT"
type = "lanswitch"
class HubNode(CoreNetwork):
"""
Provides hub functionality within a core node, forwards packets to all bridge
ports by turning off MAC address learning.
"""
apitype = NodeTypes.HUB.value
policy = "ACCEPT"
type = "hub"
def __init__(self, session, _id=None, name=None, start=True):
"""
Creates a HubNode instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node namee
:param bool start: start flag
:raises CoreCommandError: when there is a command exception
"""
CoreNetwork.__init__(self, session, _id, name, start)
# TODO: move to startup method
if start:
utils.check_cmd([constants.BRCTL_BIN, "setageing", self.brname, "0"])
class WlanNode(CoreNetwork):
"""
Provides wireless lan functionality within a core node.
"""
apitype = NodeTypes.WIRELESS_LAN.value
linktype = LinkTypes.WIRELESS.value
policy = "DROP"
type = "wlan"
def __init__(self, session, _id=None, name=None, start=True, policy=None):
"""
Create a WlanNode instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node name
:param bool start: start flag
:param policy: wlan policy
"""
CoreNetwork.__init__(self, session, _id, name, start, policy)
# wireless model such as basic range
self.model = None
# mobility model such as scripted
self.mobility = None
def attach(self, netif):
"""
Attach a network interface.
:param core.netns.vif.VEth netif: network interface
:return: nothing
"""
CoreNetwork.attach(self, netif)
if self.model:
netif.poshook = self.model.position_callback
if netif.node is None:
return
x, y, z = netif.node.position.get()
# invokes any netif.poshook
netif.setposition(x, y, z)
def setmodel(self, model, config):
"""
Sets the mobility and wireless model.
:param core.mobility.WirelessModel.cls model: wireless model to set to
:param dict config: configuration for model being set
:return: nothing
"""
logging.info("adding model: %s", model.name)
if model.config_type == RegisterTlvs.WIRELESS.value:
self.model = model(session=self.session, _id=self.id)
self.model.update_config(config)
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.setlinkparams()
elif model.config_type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)
def update_mobility(self, config):
if not self.mobility:
raise ValueError("no mobility set to update for node(%s)", self.id)
self.mobility.set_configs(config, node_id=self.id)
def updatemodel(self, config):
if not self.model:
raise ValueError("no model set to update for node(%s)", self.id)
logging.info("node(%s) updating model(%s): %s", self.id, self.model.name, config)
self.model.set_configs(config, node_id=self.id)
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.updateconfig()
def all_link_data(self, flags):
"""
Retrieve all link data.
:param flags: message flags
:return: list of link data
:rtype: list[core.data.LinkData]
"""
all_links = CoreNetwork.all_link_data(self, flags)
if self.model:
all_links.extend(self.model.all_link_data(flags))
return all_links
class TunnelNode(GreTapBridge):
"""
Provides tunnel functionality in a core node.
"""
apitype = NodeTypes.TUNNEL.value
policy = "ACCEPT"
type = "tunnel"

View file

@ -0,0 +1,29 @@
"""
Provides default node maps that can be used to run core with.
"""
import core.nodes.base
import core.nodes.network
import core.nodes.physical
from core.emane.nodes import EmaneNet
from core.emane.nodes import EmaneNode
from core.emulator.enumerations import NodeTypes
from core.nodes.network import GreTapBridge
from core.nodes import physical
# legacy core nodes, that leverage linux bridges
NODES = {
NodeTypes.DEFAULT: core.nodes.base.CoreNode,
NodeTypes.PHYSICAL: physical.PhysicalNode,
NodeTypes.TBD: None,
NodeTypes.SWITCH: core.nodes.network.SwitchNode,
NodeTypes.HUB: core.nodes.network.HubNode,
NodeTypes.WIRELESS_LAN: core.nodes.network.WlanNode,
NodeTypes.RJ45: core.nodes.physical.Rj45Node,
NodeTypes.TUNNEL: core.nodes.network.TunnelNode,
NodeTypes.KTUNNEL: None,
NodeTypes.EMANE: EmaneNode,
NodeTypes.EMANE_NET: EmaneNet,
NodeTypes.TAP_BRIDGE: GreTapBridge,
NodeTypes.PEER_TO_PEER: core.nodes.network.PtpNet,
NodeTypes.CONTROL_NET: core.nodes.network.CtrlNet
}

View file

@ -8,19 +8,18 @@ import threading
from socket import AF_INET from socket import AF_INET
from socket import AF_INET6 from socket import AF_INET6
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.coreobj import PyCoreNet from core.nodes.base import CoreNetworkBase
from core.data import LinkData from core.emulator.data import LinkData
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.misc import ipaddress from core.nodes import ipaddress
from core.misc import utils from core.nodes.interface import GreTap
from core.netns.vif import GreTap from core.nodes.interface import Veth
from core.netns.vif import VEth from core.nodes.network import EbtablesQueue
from core.netns.vnet import EbtablesQueue from core.nodes.network import GreTapBridge
from core.netns.vnet import GreTapBridge
# a global object because all WLANs share the same queue # a global object because all WLANs share the same queue
# cannot have multiple threads invoking the ebtables commnd # cannot have multiple threads invoking the ebtables commnd
@ -41,7 +40,7 @@ def ebtables_commands(call, commands):
call(command) call(command)
class OvsNet(PyCoreNet): class OvsNet(CoreNetworkBase):
""" """
Used to be LxBrNet. Used to be LxBrNet.
@ -62,7 +61,7 @@ class OvsNet(PyCoreNet):
:return: :return:
""" """
PyCoreNet.__init__(self, session, _id, name, start) CoreNetworkBase.__init__(self, session, _id, name, start)
if policy: if policy:
self.policy = policy self.policy = policy
@ -129,13 +128,13 @@ class OvsNet(PyCoreNet):
utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname]) utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname])
utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"]) utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"])
PyCoreNet.attach(self, interface) CoreNetworkBase.attach(self, interface)
def detach(self, interface): def detach(self, interface):
if self.up: if self.up:
utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname]) utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname])
PyCoreNet.detach(self, interface) CoreNetworkBase.detach(self, interface)
def linked(self, interface_one, interface_two): def linked(self, interface_one, interface_two):
# check if the network interfaces are attached to this network # check if the network interfaces are attached to this network
@ -297,7 +296,7 @@ class OvsNet(PyCoreNet):
if len(name) >= 16: if len(name) >= 16:
raise ValueError("interface name %s too long" % name) raise ValueError("interface name %s too long" % name)
interface = VEth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up) interface = Veth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up)
self.attach(interface) self.attach(interface)
if network.up: if network.up:
# this is similar to net.attach() but uses netif.name instead # this is similar to net.attach() but uses netif.name instead
@ -598,7 +597,7 @@ class OvsWlanNode(OvsNet):
logging.info("adding model %s", model.name) logging.info("adding model %s", model.name)
if model.type == RegisterTlvs.WIRELESS.value: if model.type == RegisterTlvs.WIRELESS.value:
self.model = model(session=self.session, object_id=self.id, config=config) self.model = model(session=self.session, _id=self.id, config=config)
if self.model.position_callback: if self.model.position_callback:
for interface in self.netifs(): for interface in self.netifs():
interface.poshook = self.model.position_callback interface.poshook = self.model.position_callback
@ -607,7 +606,7 @@ class OvsWlanNode(OvsNet):
interface.poshook(interface, x, y, z) interface.poshook(interface, x, y, z)
self.model.setlinkparams() self.model.setlinkparams()
elif model.type == RegisterTlvs.MOBILITY.value: elif model.type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, object_id=self.id, config=config) self.mobility = model(session=self.session, _id=self.id, config=config)
def updatemodel(self, config): def updatemodel(self, config):
if not self.model: if not self.model:

View file

@ -0,0 +1,544 @@
"""
PhysicalNode class for including real systems in the emulated network.
"""
import logging
import os
import subprocess
import threading
from core import CoreCommandError, utils
from core import constants
from core.nodes.base import CoreNodeBase
from core.nodes.interface import CoreInterface
from core.emulator.enumerations import NodeTypes
from core.nodes.network import GreTap
from core.nodes.network import CoreNetwork
class PhysicalNode(CoreNodeBase):
def __init__(self, session, _id=None, name=None, nodedir=None, start=True):
CoreNodeBase.__init__(self, session, _id, name, start=start)
self.nodedir = nodedir
self.up = start
self.lock = threading.RLock()
self._mounts = []
if start:
self.startup()
def startup(self):
with self.lock:
self.makenodedir()
def shutdown(self):
if not self.up:
return
with self.lock:
while self._mounts:
_source, target = self._mounts.pop(-1)
self.umount(target)
for netif in self.netifs():
netif.shutdown()
self.rmnodedir()
def termcmdstring(self, sh="/bin/sh"):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
return sh
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
os.chdir(self.nodedir)
status = utils.cmd(args, wait)
return status
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
os.chdir(self.nodedir)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
status = p.wait()
return status, stdout.strip()
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return output.strip()
def shcmd(self, cmdstr, sh="/bin/sh"):
return self.cmd([sh, "-c", cmdstr])
def sethwaddr(self, ifindex, addr):
"""
same as SimpleLxcNode.sethwaddr()
"""
self._netif[ifindex].sethwaddr(addr)
ifname = self.ifname(ifindex)
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)])
def addaddr(self, ifindex, addr):
"""
same as SimpleLxcNode.addaddr()
"""
if self.up:
self.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)])
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
"""
same as SimpleLxcNode.deladdr()
"""
try:
self._netif[ifindex].deladdr(addr)
except ValueError:
logging.exception("trying to delete unknown address: %s", addr)
if self.up:
self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
def adoptnetif(self, netif, ifindex, hwaddr, addrlist):
"""
The broker builds a GreTap tunnel device to this physical node.
When a link message is received linking this node to another part of
the emulation, no new interface is created; instead, adopt the
GreTap netif as the node interface.
"""
netif.name = "gt%d" % ifindex
netif.node = self
self.addnetif(netif, ifindex)
# use a more reasonable name, e.g. "gt0" instead of "gt.56286.150"
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "down"])
self.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "name", netif.name])
netif.localname = netif.name
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
for addr in utils.make_tuple(addrlist):
self.addaddr(ifindex, addr)
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"])
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
"""
Apply tc queing disciplines using LxBrNet.linkconfig()
"""
# borrow the tc qdisc commands from LxBrNet.linkconfig()
linux_bridge = CoreNetwork(session=self.session, start=False)
linux_bridge.up = True
linux_bridge.linkconfig(netif, bw=bw, delay=delay, loss=loss, duplicate=duplicate, jitter=jitter, netif2=netif2)
del linux_bridge
def newifindex(self):
with self.lock:
while self.ifindex in self._netif:
self.ifindex += 1
ifindex = self.ifindex
self.ifindex += 1
return ifindex
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
logging.info("creating interface")
if not addrlist:
addrlist = []
if self.up and net is None:
raise NotImplementedError
if ifindex is None:
ifindex = self.newifindex()
if self.up:
# this is reached when this node is linked to a network node
# tunnel to net not built yet, so build it now and adopt it
gt = self.session.broker.addnettunnel(net.id)
if gt is None or len(gt) != 1:
raise ValueError("error building tunnel from adding a new network interface: %s" % gt)
gt = gt[0]
net.detach(gt)
self.adoptnetif(gt, ifindex, hwaddr, addrlist)
return ifindex
# this is reached when configuring services (self.up=False)
if ifname is None:
ifname = "gt%d" % ifindex
netif = GreTap(node=self, name=ifname, session=self.session, start=False)
self.adoptnetif(netif, ifindex, hwaddr, addrlist)
return ifindex
def privatedir(self, path):
if path[0] != "/":
raise ValueError("path not fully qualified: %s" % path)
hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip('/').replace('/', '.'))
os.mkdir(hostpath)
self.mount(hostpath, path)
def mount(self, source, target):
source = os.path.abspath(source)
logging.info("mounting %s at %s", source, target)
os.makedirs(target)
self.check_cmd([constants.MOUNT_BIN, "--bind", source, target])
self._mounts.append((source, target))
def umount(self, target):
logging.info("unmounting '%s'" % target)
try:
self.check_cmd([constants.UMOUNT_BIN, "-l", target])
except CoreCommandError:
logging.exception("unmounting failed for %s", target)
def opennodefile(self, filename, mode="w"):
dirname, basename = os.path.split(filename)
if not basename:
raise ValueError("no basename for filename: " + filename)
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")
dirname = os.path.join(self.nodedir, dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname, mode=0755)
hostfilename = os.path.join(dirname, basename)
return open(hostfilename, mode)
def nodefile(self, filename, contents, mode=0644):
with self.opennodefile(filename, "w") as node_file:
node_file.write(contents)
os.chmod(node_file.name, mode)
logging.info("created nodefile: '%s'; mode: 0%o", node_file.name, mode)
class Rj45Node(CoreNodeBase, CoreInterface):
"""
RJ45Node is a physical interface on the host linked to the emulated
network.
"""
apitype = NodeTypes.RJ45.value
type = "rj45"
def __init__(self, session, _id=None, name=None, mtu=1500, start=True):
"""
Create an RJ45Node instance.
:param core.session.Session session: core session instance
:param int _id: node id
:param str name: node name
:param mtu: rj45 mtu
:param bool start: start flag
:return:
"""
CoreNodeBase.__init__(self, session, _id, name, start=start)
CoreInterface.__init__(self, node=self, name=name, mtu=mtu)
self.up = False
self.lock = threading.RLock()
self.ifindex = None
# the following are PyCoreNetIf attributes
self.transport_type = "raw"
self.localname = name
self.old_up = False
self.old_addrs = []
if start:
self.startup()
def startup(self):
"""
Set the interface in the up state.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
# interface will also be marked up during net.attach()
self.savestate()
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
self.up = True
def shutdown(self):
"""
Bring the interface down. Remove any addresses and queuing
disciplines.
:return: nothing
"""
if not self.up:
return
try:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"])
utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname])
utils.check_cmd([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"])
except CoreCommandError:
logging.exception("error shutting down")
self.up = False
self.restorestate()
# TODO: issue in that both classes inherited from provide the same method with different signatures
def attachnet(self, net):
"""
Attach a network.
:param core.coreobj.PyCoreNet net: network to attach
:return: nothing
"""
CoreInterface.attachnet(self, net)
# TODO: issue in that both classes inherited from provide the same method with different signatures
def detachnet(self):
"""
Detach a network.
:return: nothing
"""
CoreInterface.detachnet(self)
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
"""
This is called when linking with another node. Since this node
represents an interface, we do not create another object here,
but attach ourselves to the given network.
:param core.coreobj.PyCoreNet net: new network instance
:param list[str] addrlist: address list
:param str hwaddr: hardware address
:param int ifindex: interface index
:param str ifname: interface name
:return: interface index
:rtype: int
:raises ValueError: when an interface has already been created, one max
"""
with self.lock:
if ifindex is None:
ifindex = 0
if self.net is not None:
raise ValueError("RJ45 nodes support at most 1 network interface")
self._netif[ifindex] = self
# PyCoreNetIf.node is self
self.node = self
self.ifindex = ifindex
if net is not None:
self.attachnet(net)
if addrlist:
for addr in utils.make_tuple(addrlist):
self.addaddr(addr)
return ifindex
def delnetif(self, ifindex):
"""
Delete a network interface.
:param int ifindex: interface index to delete
:return: nothing
"""
if ifindex is None:
ifindex = 0
self._netif.pop(ifindex)
if ifindex == self.ifindex:
self.shutdown()
else:
raise ValueError("ifindex %s does not exist" % ifindex)
def netif(self, ifindex, net=None):
"""
This object is considered the network interface, so we only
return self here. This keeps the RJ45Node compatible with
real nodes.
:param int ifindex: interface index to retrieve
:param net: network to retrieve
:return: a network interface
:rtype: core.coreobj.PyCoreNetIf
"""
if net is not None and net == self.net:
return self
if ifindex is None:
ifindex = 0
if ifindex == self.ifindex:
return self
return None
def getifindex(self, netif):
"""
Retrieve network interface index.
:param core.coreobj.PyCoreNetIf netif: network interface to retrieve index for
:return: interface index, None otherwise
:rtype: int
"""
if netif != self:
return None
return self.ifindex
def addaddr(self, addr):
"""
Add address to to network interface.
:param str addr: address to add
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name])
CoreInterface.addaddr(self, addr)
def deladdr(self, addr):
"""
Delete address from network interface.
:param str addr: address to delete
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
if self.up:
utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name])
CoreInterface.deladdr(self, addr)
def savestate(self):
"""
Save the addresses and other interface state before using the
interface for emulation purposes. TODO: save/restore the PROMISC flag
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
self.old_up = False
self.old_addrs = []
args = [constants.IP_BIN, "addr", "show", "dev", self.localname]
output = utils.check_cmd(args)
for line in output.split("\n"):
items = line.split()
if len(items) < 2:
continue
if items[1] == "%s:" % self.localname:
flags = items[2][1:-1].split(",")
if "UP" in flags:
self.old_up = True
elif items[0] == "inet":
self.old_addrs.append((items[1], items[3]))
elif items[0] == "inet6":
if items[1][:4] == "fe80":
continue
self.old_addrs.append((items[1], None))
def restorestate(self):
"""
Restore the addresses and other interface state after using it.
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
for addr in self.old_addrs:
if addr[1] is None:
utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "dev", self.localname])
else:
utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "brd", addr[1], "dev", self.localname])
if self.old_up:
utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"])
def setposition(self, x=None, y=None, z=None):
"""
Uses setposition from both parent classes.
:param float x: x position
:param float y: y position
:param float z: z position
:return: True if position changed, False otherwise
:rtype: bool
"""
result = CoreNodeBase.setposition(self, x, y, z)
CoreInterface.setposition(self, x, y, z)
return result
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: exist status and combined stdout and stderr
:rtype: tuple[int, str]
:raises CoreCommandError: when a non-zero exit status occurs
"""
raise NotImplementedError
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
raise NotImplementedError
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
raise NotImplementedError
def termcmdstring(self, sh):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
raise NotImplementedError

View file

@ -1,245 +0,0 @@
"""
PhysicalNode class for including real systems in the emulated network.
"""
import logging
import os
import subprocess
import threading
from core import CoreCommandError
from core import constants
from core.coreobj import PyCoreNode
from core.misc import utils
from core.netns.vnet import GreTap
from core.netns.vnet import LxBrNet
class PhysicalNode(PyCoreNode):
def __init__(self, session, _id=None, name=None, nodedir=None, start=True):
PyCoreNode.__init__(self, session, _id, name, start=start)
self.nodedir = nodedir
self.up = start
self.lock = threading.RLock()
self._mounts = []
if start:
self.startup()
def startup(self):
with self.lock:
self.makenodedir()
def shutdown(self):
if not self.up:
return
with self.lock:
while self._mounts:
_source, target = self._mounts.pop(-1)
self.umount(target)
for netif in self.netifs():
netif.shutdown()
self.rmnodedir()
def termcmdstring(self, sh="/bin/sh"):
"""
Create a terminal command string.
:param str sh: shell to execute command in
:return: str
"""
return sh
def cmd(self, args, wait=True):
"""
Runs shell command on node, with option to not wait for a result.
:param list[str]|str args: command to run
:param bool wait: wait for command to exit, defaults to True
:return: exit status for command
:rtype: int
"""
os.chdir(self.nodedir)
status = utils.cmd(args, wait)
return status
def cmd_output(self, args):
"""
Runs shell command on node and get exit status and output.
:param list[str]|str args: command to run
:return: exit status and combined stdout and stderr
:rtype: tuple[int, str]
"""
os.chdir(self.nodedir)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
status = p.wait()
return status, stdout.strip()
def check_cmd(self, args):
"""
Runs shell command on node.
:param list[str]|str args: command to run
:return: combined stdout and stderr
:rtype: str
:raises CoreCommandError: when a non-zero exit status occurs
"""
status, output = self.cmd_output(args)
if status:
raise CoreCommandError(status, args, output)
return output.strip()
def shcmd(self, cmdstr, sh="/bin/sh"):
return self.cmd([sh, "-c", cmdstr])
def sethwaddr(self, ifindex, addr):
"""
same as SimpleLxcNode.sethwaddr()
"""
self._netif[ifindex].sethwaddr(addr)
ifname = self.ifname(ifindex)
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)])
def addaddr(self, ifindex, addr):
"""
same as SimpleLxcNode.addaddr()
"""
if self.up:
self.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)])
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
"""
same as SimpleLxcNode.deladdr()
"""
try:
self._netif[ifindex].deladdr(addr)
except ValueError:
logging.exception("trying to delete unknown address: %s", addr)
if self.up:
self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)])
def adoptnetif(self, netif, ifindex, hwaddr, addrlist):
"""
The broker builds a GreTap tunnel device to this physical node.
When a link message is received linking this node to another part of
the emulation, no new interface is created; instead, adopt the
GreTap netif as the node interface.
"""
netif.name = "gt%d" % ifindex
netif.node = self
self.addnetif(netif, ifindex)
# use a more reasonable name, e.g. "gt0" instead of "gt.56286.150"
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "down"])
self.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "name", netif.name])
netif.localname = netif.name
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
for addr in utils.make_tuple(addrlist):
self.addaddr(ifindex, addr)
if self.up:
self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"])
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
"""
Apply tc queing disciplines using LxBrNet.linkconfig()
"""
# borrow the tc qdisc commands from LxBrNet.linkconfig()
linux_bridge = LxBrNet(session=self.session, start=False)
linux_bridge.up = True
linux_bridge.linkconfig(netif, bw=bw, delay=delay, loss=loss, duplicate=duplicate, jitter=jitter, netif2=netif2)
del linux_bridge
def newifindex(self):
with self.lock:
while self.ifindex in self._netif:
self.ifindex += 1
ifindex = self.ifindex
self.ifindex += 1
return ifindex
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None):
logging.info("creating interface")
if not addrlist:
addrlist = []
if self.up and net is None:
raise NotImplementedError
if ifindex is None:
ifindex = self.newifindex()
if self.up:
# this is reached when this node is linked to a network node
# tunnel to net not built yet, so build it now and adopt it
gt = self.session.broker.addnettunnel(net.id)
if gt is None or len(gt) != 1:
raise ValueError("error building tunnel from adding a new network interface: %s" % gt)
gt = gt[0]
net.detach(gt)
self.adoptnetif(gt, ifindex, hwaddr, addrlist)
return ifindex
# this is reached when configuring services (self.up=False)
if ifname is None:
ifname = "gt%d" % ifindex
netif = GreTap(node=self, name=ifname, session=self.session, start=False)
self.adoptnetif(netif, ifindex, hwaddr, addrlist)
return ifindex
def privatedir(self, path):
if path[0] != "/":
raise ValueError("path not fully qualified: %s" % path)
hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip('/').replace('/', '.'))
os.mkdir(hostpath)
self.mount(hostpath, path)
def mount(self, source, target):
source = os.path.abspath(source)
logging.info("mounting %s at %s", source, target)
os.makedirs(target)
self.check_cmd([constants.MOUNT_BIN, "--bind", source, target])
self._mounts.append((source, target))
def umount(self, target):
logging.info("unmounting '%s'" % target)
try:
self.check_cmd([constants.UMOUNT_BIN, "-l", target])
except CoreCommandError:
logging.exception("unmounting failed for %s", target)
def opennodefile(self, filename, mode="w"):
dirname, basename = os.path.split(filename)
if not basename:
raise ValueError("no basename for filename: " + filename)
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")
dirname = os.path.join(self.nodedir, dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname, mode=0755)
hostfilename = os.path.join(dirname, basename)
return open(hostfilename, mode)
def nodefile(self, filename, contents, mode=0644):
with self.opennodefile(filename, "w") as node_file:
node_file.write(contents)
os.chmod(node_file.name, mode)
logging.info("created nodefile: '%s'; mode: 0%o", node_file.name, mode)

View file

View file

@ -7,16 +7,15 @@ import socket
from urlparse import urlparse from urlparse import urlparse
from core import constants from core import constants
from core.coreobj import PyCoreNet from core.nodes.base import NodeBase, CoreNetworkBase
from core.coreobj import PyCoreObj from core.emulator.enumerations import EventTypes
from core.enumerations import EventTypes from core.emulator.enumerations import LinkTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import LinkTypes
from core.enumerations import LinkTypes from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageTypes
from core.enumerations import MessageTypes from core.emulator.enumerations import NodeTlvs
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTypes
from core.enumerations import NodeTypes from core.nodes import nodeutils
from core.misc import nodeutils
# TODO: A named tuple may be more appropriate, than abusing a class dict like this # TODO: A named tuple may be more appropriate, than abusing a class dict like this
@ -321,22 +320,20 @@ class Sdt(object):
:return: nothing :return: nothing
""" """
nets = [] nets = []
with self.session._objects_lock: with self.session._nodes_lock:
for obj in self.session.objects.itervalues(): for node in self.session.nodes.itervalues():
if isinstance(obj, PyCoreNet): if isinstance(node, CoreNetworkBase):
nets.append(obj) nets.append(node)
if not isinstance(obj, PyCoreObj): if not isinstance(node, NodeBase):
continue continue
(x, y, z) = obj.getposition() (x, y, z) = node.getposition()
if x is None or y is None: if x is None or y is None:
continue continue
self.updatenode(obj.id, MessageFlags.ADD.value, x, y, z, self.updatenode(node.id, MessageFlags.ADD.value, x, y, z, node.name, node.type, node.icon)
obj.name, obj.type, obj.icon)
for nodenum in sorted(self.remotes.keys()): for nodenum in sorted(self.remotes.keys()):
r = self.remotes[nodenum] r = self.remotes[nodenum]
x, y, z = r.pos x, y, z = r.pos
self.updatenode(nodenum, MessageFlags.ADD.value, x, y, z, self.updatenode(nodenum, MessageFlags.ADD.value, x, y, z, r.name, r.type, r.icon)
r.name, r.type, r.icon)
for net in nets: for net in nets:
all_links = net.all_link_data(flags=MessageFlags.ADD.value) all_links = net.all_link_data(flags=MessageFlags.ADD.value)
@ -411,7 +408,7 @@ class Sdt(object):
nodetype = None nodetype = None
try: try:
node = self.session.get_object(nodenum) node = self.session.get_node(nodenum)
except KeyError: except KeyError:
node = None node = None
if node: if node:
@ -472,7 +469,7 @@ class Sdt(object):
return True return True
else: else:
try: try:
n = self.session.get_object(nodenum) n = self.session.get_node(nodenum)
except KeyError: except KeyError:
return False return False
if nodeutils.is_node(n, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): if nodeutils.is_node(n, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)):

View file

@ -6,7 +6,7 @@ __all__ is automatically loaded by the main core module.
""" """
import os import os
from core.service import ServiceManager from core.services.coreservices import ServiceManager
_PATH = os.path.abspath(os.path.dirname(__file__)) _PATH = os.path.abspath(os.path.dirname(__file__))

View file

@ -2,7 +2,7 @@
bird.py: defines routing services provided by the BIRD Internet Routing Daemon. bird.py: defines routing services provided by the BIRD Internet Routing Daemon.
""" """
from core.service import CoreService from core.services.coreservices import CoreService
class Bird(CoreService): class Bird(CoreService):

View file

@ -14,11 +14,10 @@ from multiprocessing.pool import ThreadPool
import enum import enum
from core.constants import which from core.constants import which
from core import CoreCommandError from core import CoreCommandError, utils
from core.data import FileData from core.emulator.data import FileData
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import RegisterTlvs from core.emulator.enumerations import RegisterTlvs
from core.misc import utils
class ServiceBootError(Exception): class ServiceBootError(Exception):
@ -58,7 +57,7 @@ class ServiceDependencies(object):
Generates the boot paths for the services provided to the class. Generates the boot paths for the services provided to the class.
:return: list of services to boot, in order :return: list of services to boot, in order
:rtype: list[core.service.CoreService] :rtype: list[core.coreservices.CoreService]
""" """
paths = [] paths = []
for service in self.node_services.itervalues(): for service in self.node_services.itervalues():
@ -126,7 +125,7 @@ class ServiceShim(object):
Convert service properties into a string list of key=value pairs, Convert service properties into a string list of key=value pairs,
separated by "|". separated by "|".
:param core.netns.nodes.CoreNode node: node to get value list for :param core.netns.vnode.CoreNode node: node to get value list for
:param CoreService service: service to get value list for :param CoreService service: service to get value list for
:return: value list string :return: value list string
:rtype: str :rtype: str
@ -556,7 +555,7 @@ class CoreServices(object):
""" """
Stop all services on a node. Stop all services on a node.
:param core.netns.nodes.CoreNode node: node to stop services on :param core.netns.vnode.CoreNode node: node to stop services on
:return: nothing :return: nothing
""" """
for service in node.services: for service in node.services:

View file

@ -99,8 +99,8 @@ Limitations:
import logging import logging
from core.service import CoreService from core.services.coreservices import CoreService
from core.service import ServiceManager from core.services.coreservices import ServiceManager
try: try:
from docker import Client from docker import Client

View file

@ -1,6 +1,6 @@
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import nodeutils from core.nodes import nodeutils
from core.service import CoreService from core.services.coreservices import CoreService
from core.xml import emanexml from core.xml import emanexml
@ -21,7 +21,7 @@ class EmaneTransportService(CoreService):
if filename == cls.configs[0]: if filename == cls.configs[0]:
transport_commands = [] transport_commands = []
for interface in node.netifs(sort=True): for interface in node.netifs(sort=True):
network_node = node.session.get_object(interface.net.id) network_node = node.session.get_node(interface.net.id)
if nodeutils.is_node(network_node, NodeTypes.EMANE): if nodeutils.is_node(network_node, NodeTypes.EMANE):
config = node.session.emane.get_configs(network_node.id, network_node.model.name) config = node.session.emane.get_configs(network_node.id, network_node.model.name)
if config and emanexml.is_external(config): if config and emanexml.is_external(config):

View file

@ -4,10 +4,9 @@ Assumes installation of FRR via https://deb.frrouting.org/
""" """
from core import constants from core import constants
from core.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.misc import ipaddress from core.nodes import nodeutils, ipaddress
from core.misc import nodeutils from core.services.coreservices import CoreService
from core.service import CoreService
class FRRZebra(CoreService): class FRRZebra(CoreService):

View file

@ -3,9 +3,9 @@ nrl.py: defines services provided by NRL protolib tools hosted here:
http://www.nrl.navy.mil/itd/ncs/products http://www.nrl.navy.mil/itd/ncs/products
""" """
from core.misc import utils from core import utils
from core.misc.ipaddress import Ipv4Prefix from core.nodes.ipaddress import Ipv4Prefix
from core.service import CoreService from core.services.coreservices import CoreService
class NrlService(CoreService): class NrlService(CoreService):

View file

@ -3,10 +3,9 @@ quagga.py: defines routing services provided by Quagga.
""" """
from core import constants from core import constants
from core.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.misc import ipaddress from core.nodes import nodeutils, ipaddress
from core.misc import nodeutils from core.services.coreservices import CoreService
from core.service import CoreService
class Zebra(CoreService): class Zebra(CoreService):

View file

@ -4,7 +4,7 @@ sdn.py defines services to start Open vSwitch and the Ryu SDN Controller.
import re import re
from core.service import CoreService from core.services.coreservices import CoreService
class SdnService(CoreService): class SdnService(CoreService):

View file

@ -6,7 +6,7 @@ firewall)
import logging import logging
from core import constants from core import constants
from core.service import CoreService from core.services.coreservices import CoreService
class VPNClient(CoreService): class VPNClient(CoreService):

View file

@ -2,7 +2,7 @@
ucarp.py: defines high-availability IP address controlled by ucarp ucarp.py: defines high-availability IP address controlled by ucarp
""" """
from core.service import CoreService from core.services.coreservices import CoreService
UCARP_ETC = "/usr/local/etc/ucarp" UCARP_ETC = "/usr/local/etc/ucarp"

View file

@ -4,12 +4,11 @@ utility.py: defines miscellaneous utility services.
import os import os
from core import CoreCommandError from core import CoreCommandError, utils
from core import constants from core import constants
from core.misc import utils from core.nodes.ipaddress import Ipv4Prefix
from core.misc.ipaddress import Ipv4Prefix from core.nodes.ipaddress import Ipv6Prefix
from core.misc.ipaddress import Ipv6Prefix from core.services.coreservices import CoreService
from core.service import CoreService
class UtilService(CoreService): class UtilService(CoreService):

View file

@ -4,7 +4,7 @@ xorp.py: defines routing services provided by the XORP routing suite.
import logging import logging
from core.service import CoreService from core.services.coreservices import CoreService
class XorpRtrmgr(CoreService): class XorpRtrmgr(CoreService):

View file

@ -1,15 +1,14 @@
import logging import logging
from lxml import etree from lxml import etree
from core import coreobj import core.nodes.base
import core.nodes.physical
from core.emulator.emudata import InterfaceData from core.emulator.emudata import InterfaceData
from core.emulator.emudata import LinkOptions from core.emulator.emudata import LinkOptions
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import nodeutils from core.nodes import nodeutils
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.netns import nodes
def write_xml_file(xml_element, file_path, doctype=None): def write_xml_file(xml_element, file_path, doctype=None):
@ -377,12 +376,12 @@ class CoreXmlWriter(object):
self.devices = etree.SubElement(self.scenario, "devices") self.devices = etree.SubElement(self.scenario, "devices")
links = [] links = []
for node in self.session.objects.itervalues(): for node in self.session.nodes.itervalues():
# network node # network node
if isinstance(node, (coreobj.PyCoreNet, nodes.RJ45Node)) and not nodeutils.is_node(node, NodeTypes.CONTROL_NET): if isinstance(node, (core.nodes.base.CoreNetworkBase, core.nodes.physical.Rj45Node)) and not nodeutils.is_node(node, NodeTypes.CONTROL_NET):
self.write_network(node) self.write_network(node)
# device node # device node
elif isinstance(node, nodes.PyCoreNode): elif isinstance(node, core.nodes.base.CoreNodeBase):
self.write_device(node) self.write_device(node)
# add known links # add known links
@ -432,7 +431,7 @@ class CoreXmlWriter(object):
# check for interface one # check for interface one
if link_data.interface1_id is not None: if link_data.interface1_id is not None:
interface_one = etree.Element("interface_one") interface_one = etree.Element("interface_one")
node = self.session.get_object(link_data.node1_id) node = self.session.get_node(link_data.node1_id)
node_interface = node.netif(link_data.interface1_id) node_interface = node.netif(link_data.interface1_id)
add_attribute(interface_one, "id", link_data.interface1_id) add_attribute(interface_one, "id", link_data.interface1_id)
@ -453,7 +452,7 @@ class CoreXmlWriter(object):
# check for interface two # check for interface two
if link_data.interface2_id is not None: if link_data.interface2_id is not None:
interface_two = etree.Element("interface_two") interface_two = etree.Element("interface_two")
node = self.session.get_object(link_data.node2_id) node = self.session.get_node(link_data.node2_id)
node_interface = node.netif(link_data.interface2_id) node_interface = node.netif(link_data.interface2_id)
add_attribute(interface_two, "id", link_data.interface2_id) add_attribute(interface_two, "id", link_data.interface2_id)

View file

@ -3,10 +3,10 @@ import socket
from lxml import etree from lxml import etree
from core import constants from core import constants, utils
from core.coreobj import PyCoreNode from core.nodes.base import CoreNodeBase
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import utils, nodeutils, ipaddress from core.nodes import nodeutils, ipaddress
def add_type(parent_element, name): def add_type(parent_element, name):
@ -100,8 +100,8 @@ class CoreXmlDeployment(object):
# servers = self.session.broker.getservernames() # servers = self.session.broker.getservernames()
# servers.remove("localhost") # servers.remove("localhost")
for node in self.session.objects.itervalues(): for node in self.session.nodes.itervalues():
if isinstance(node, PyCoreNode): if isinstance(node, CoreNodeBase):
self.add_virtual_host(physical_host, node) self.add_virtual_host(physical_host, node)
def add_physical_host(self, name): def add_physical_host(self, name):
@ -119,7 +119,7 @@ class CoreXmlDeployment(object):
return host_element return host_element
def add_virtual_host(self, physical_host, node): def add_virtual_host(self, physical_host, node):
if not isinstance(node, PyCoreNode): if not isinstance(node, CoreNodeBase):
raise TypeError("invalid node type: %s" % node) raise TypeError("invalid node type: %s" % node)
# create virtual host element # create virtual host element

View file

@ -3,8 +3,8 @@ import os
from lxml import etree from lxml import etree
from core.misc import utils from core import utils
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.xml import corexml from core.xml import corexml
_hwaddr_prefix = "02:02" _hwaddr_prefix = "02:02"
@ -101,7 +101,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
Create platform xml for a specific node. Create platform xml for a specific node.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations :param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.netns.nodes.CtrlNet control_net: control net node for this emane network :param core.nodes.network.CtrlNet control_net: control net node for this emane network
:param core.emane.nodes.EmaneNode node: node to write platform xml for :param core.emane.nodes.EmaneNode node: node to write platform xml for
:param int nem_id: nem id to use for interfaces for this node :param int nem_id: nem id to use for interfaces for this node
:param dict platform_xmls: stores platform xml elements to append nem entries to :param dict platform_xmls: stores platform xml elements to append nem entries to
@ -121,7 +121,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
nem_element = etree.Element("nem", id=str(nem_id), name=netif.localname, definition=nem_definition) nem_element = etree.Element("nem", id=str(nem_id), name=netif.localname, definition=nem_definition)
# check if this is an external transport, get default config if an interface specific one does not exist # check if this is an external transport, get default config if an interface specific one does not exist
config = emane_manager.getifcconfig(node.model.object_id, netif, node.model.name) config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
if is_external(config): if is_external(config):
nem_element.set("transport", "external") nem_element.set("transport", "external")
@ -214,7 +214,7 @@ def build_xml_files(emane_manager, node):
return return
# get model configurations # get model configurations
config = emane_manager.get_configs(node.model.object_id, node.model.name) config = emane_manager.get_configs(node.model.id, node.model.name)
if not config: if not config:
return return
@ -229,7 +229,7 @@ def build_xml_files(emane_manager, node):
for netif in node.netifs(): for netif in node.netifs():
# check for interface specific emane configuration and write xml files, if needed # check for interface specific emane configuration and write xml files, if needed
config = emane_manager.getifcconfig(node.model.object_id, netif, node.model.name) config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
if config: if config:
node.model.build_xml_files(config, netif) node.model.build_xml_files(config, netif)
@ -379,7 +379,7 @@ def _basename(emane_model, interface=None):
:return: basename used for file creation :return: basename used for file creation
:rtype: str :rtype: str
""" """
name = "n%s" % emane_model.object_id name = "n%s" % emane_model.id
if interface: if interface:
node_id = interface.node.id node_id = interface.node.id

View file

@ -9,7 +9,7 @@ from core import load_logging_config
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes from core.emulator.emudata import IpPrefixes
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
load_logging_config() load_logging_config()
@ -43,7 +43,7 @@ def example(options):
session.instantiate() session.instantiate()
# start a shell on the first node # start a shell on the first node
node = session.get_object(2) node = session.get_node(2)
node.client.term("bash") node.client.term("bash")
# shutdown session # shutdown session

View file

@ -11,7 +11,7 @@ import parser
from core import load_logging_config from core import load_logging_config
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes from core.emulator.emudata import IpPrefixes
from core.enumerations import NodeTypes, EventTypes from core.emulator.enumerations import NodeTypes, EventTypes
load_logging_config() load_logging_config()
@ -40,8 +40,8 @@ def example(options):
session.instantiate() session.instantiate()
# get nodes to run example # get nodes to run example
first_node = session.get_object(2) first_node = session.get_node(2)
last_node = session.get_object(options.nodes + 1) last_node = session.get_node(options.nodes + 1)
print "starting iperf server on node: %s" % first_node.name print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"]) first_node.cmd(["iperf", "-s", "-D"])

View file

@ -6,7 +6,7 @@
# nodestep # nodestep
from core import load_logging_config from core import load_logging_config
from core.emulator.emudata import IpPrefixes from core.emulator.emudata import IpPrefixes
from core.enumerations import NodeTypes, EventTypes from core.emulator.enumerations import NodeTypes, EventTypes
load_logging_config() load_logging_config()

View file

@ -11,8 +11,8 @@ import parser
from core import load_logging_config from core import load_logging_config
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions from core.emulator.emudata import IpPrefixes, NodeOptions
from core.enumerations import NodeTypes, EventTypes from core.emulator.enumerations import NodeTypes, EventTypes
from core.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
load_logging_config() load_logging_config()
@ -44,8 +44,8 @@ def example(options):
session.instantiate() session.instantiate()
# get nodes for example run # get nodes for example run
first_node = session.get_object(2) first_node = session.get_node(2)
last_node = session.get_object(options.nodes + 1) last_node = session.get_node(options.nodes + 1)
print "starting iperf server on node: %s" % first_node.name print "starting iperf server on node: %s" % first_node.name
first_node.cmd(["iperf", "-s", "-D"]) first_node.cmd(["iperf", "-s", "-D"])

View file

@ -1,7 +1,7 @@
import logging import logging
import time import time
from core.misc.event import EventLoop from core.location.event import EventLoop
def main(): def main():

View file

@ -1,7 +1,6 @@
import logging import logging
from core.grpc import client from core.api.grpc import client, core_pb2
from core.grpc import core_pb2
def log_event(event): def log_event(event):

View file

@ -2,8 +2,8 @@
Sample user-defined service. Sample user-defined service.
""" """
from core.service import CoreService from core.services.coreservices import CoreService
from core.service import ServiceMode from core.services.coreservices import ServiceMode
## Custom CORE Service ## Custom CORE Service

View file

@ -14,23 +14,23 @@ import datetime
import optparse import optparse
import sys import sys
from core.api import coreapi import core.nodes.base
from core.api import dataconversion import core.nodes.network
from core.api.coreapi import CoreExecuteTlv from core.api.tlv import coreapi, dataconversion
from core.enumerations import CORE_API_PORT from core.api.tlv.coreapi import CoreExecuteTlv
from core.enumerations import EventTlvs from core.emulator.enumerations import CORE_API_PORT
from core.enumerations import EventTypes from core.emulator.enumerations import EventTlvs
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import EventTypes
from core.enumerations import LinkTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTlvs
from core.enumerations import MessageFlags from core.emulator.enumerations import LinkTypes
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageFlags
from core.misc import ipaddress from core.emulator.enumerations import MessageTypes
from core.netns import nodes from core.nodes import ipaddress
# declare classes for use with Broker # declare classes for use with Broker
from core.session import Session from core.emulator.session import Session
# node list (count from 1) # node list (count from 1)
n = [None] n = [None]
@ -136,7 +136,7 @@ def main():
session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata)) session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata))
flags = MessageFlags.ADD.value flags = MessageFlags.ADD.value
switch = nodes.SwitchNode(session=session, name="switch", start=False) switch = core.nodes.network.SwitchNode(session=session, name="switch", start=False)
switch.setposition(x=80, y=50) switch.setposition(x=80, y=50)
switch.server = daemon switch.server = daemon
switch_data = switch.data(flags) switch_data = switch.data(flags)
@ -149,7 +149,7 @@ def main():
# create remote nodes via API # create remote nodes via API
for i in xrange(1, number_of_nodes + 1): for i in xrange(1, number_of_nodes + 1):
node = nodes.CoreNode(session=session, _id=i, name="n%d" % i, start=False) node = core.nodes.base.CoreNode(session=session, _id=i, name="n%d" % i, start=False)
node.setposition(x=150 * i, y=150) node.setposition(x=150 * i, y=150)
node.server = daemon node.server = daemon
node_data = node.data(flags) node_data = node.data(flags)

View file

@ -13,12 +13,13 @@ import datetime
import optparse import optparse
import sys import sys
import core.nodes.base
import core.nodes.network
from core import constants from core import constants
from core.api import coreapi, dataconversion from core.api.tlv import coreapi, dataconversion
from core.enumerations import CORE_API_PORT, EventTypes, EventTlvs, LinkTlvs, LinkTypes, MessageFlags from core.emulator.enumerations import CORE_API_PORT, EventTypes, EventTlvs, LinkTlvs, LinkTypes, MessageFlags
from core.misc import ipaddress from core.nodes import ipaddress
from core.netns import nodes from core.emulator.session import Session
from core.session import Session
# node list (count from 1) # node list (count from 1)
n = [None] n = [None]
@ -73,14 +74,14 @@ def main():
tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value) tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value)
session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata)) session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata))
switch = session.add_object(cls=nodes.SwitchNode, name="switch") switch = session.create_node(cls=core.nodes.network.SwitchNode, name="switch")
switch.setposition(x=80, y=50) switch.setposition(x=80, y=50)
num_local = options.numnodes / 2 num_local = options.numnodes / 2
num_remote = options.numnodes / 2 + options.numnodes % 2 num_remote = options.numnodes / 2 + options.numnodes % 2
print "creating %d (%d local / %d remote) nodes with addresses from %s" % \ print "creating %d (%d local / %d remote) nodes with addresses from %s" % \
(options.numnodes, num_local, num_remote, prefix) (options.numnodes, num_local, num_remote, prefix)
for i in xrange(1, num_local + 1): for i in xrange(1, num_local + 1):
node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, _id=i) node = session.create_node(cls=core.nodes.base.CoreNode, name="n%d" % i, _id=i)
node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
node.setposition(x=150 * i, y=150) node.setposition(x=150 * i, y=150)
@ -91,7 +92,7 @@ def main():
# create remote nodes via API # create remote nodes via API
for i in xrange(num_local + 1, options.numnodes + 1): for i in xrange(num_local + 1, options.numnodes + 1):
node = nodes.CoreNode(session=session, _id=i, name="n%d" % i, start=False) node = core.nodes.base.CoreNode(session=session, _id=i, name="n%d" % i, start=False)
node.setposition(x=150 * i, y=150) node.setposition(x=150 * i, y=150)
node.server = slave node.server = slave
n.append(node) n.append(node)

View file

@ -19,10 +19,11 @@ import shutil
import sys import sys
import time import time
import core.nodes.base
import core.nodes.network
from core import constants from core import constants
from core.misc import ipaddress from core.nodes import ipaddress
from core.netns import nodes from core.emulator.session import Session
from core.session import Session
GBD = 1024.0 * 1024.0 GBD = 1024.0 * 1024.0
@ -135,7 +136,7 @@ def main():
lfp.flush() lfp.flush()
session = Session(1) session = Session(1)
switch = session.add_object(cls=nodes.SwitchNode) switch = session.create_node(cls=core.nodes.network.SwitchNode)
switchlist.append(switch) switchlist.append(switch)
print "Added bridge %s (%d)." % (switch.brname, len(switchlist)) print "Added bridge %s (%d)." % (switch.brname, len(switchlist))
@ -146,7 +147,7 @@ def main():
# optionally add a bridge (options.bridges nodes per bridge) # optionally add a bridge (options.bridges nodes per bridge)
try: try:
if 0 < options.bridges <= switch.numnetif(): if 0 < options.bridges <= switch.numnetif():
switch = session.add_object(cls=nodes.SwitchNode) switch = session.create_node(cls=core.nodes.network.SwitchNode)
switchlist.append(switch) switchlist.append(switch)
print "\nAdded bridge %s (%d) for node %d." % (switch.brname, len(switchlist), i) print "\nAdded bridge %s (%d) for node %d." % (switch.brname, len(switchlist), i)
except Exception, e: except Exception, e:
@ -155,7 +156,7 @@ def main():
# create a node # create a node
try: try:
n = session.add_object(cls=nodes.LxcNode, name="n%d" % i) n = session.create_node(cls=core.nodes.base.CoreNode, name="n%d" % i)
n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
if options.services is not None: if options.services is not None:

View file

@ -15,14 +15,13 @@ import sys
import time import time
from string import Template from string import Template
import core.nodes.base
import core.nodes.network
from core.constants import QUAGGA_STATE_DIR from core.constants import QUAGGA_STATE_DIR
from core.nodes import ipaddress
from core.misc import ipaddress from core.utils import check_cmd
from core.misc.utils import check_cmd
from core.netns import nodes
# this is the /etc/core/core.conf default # this is the /etc/core/core.conf default
from core.session import Session from core.emulator.session import Session
quagga_sbin_search = ("/usr/local/sbin", "/usr/sbin", "/usr/lib/quagga") quagga_sbin_search = ("/usr/local/sbin", "/usr/sbin", "/usr/lib/quagga")
quagga_path = "zebra" quagga_path = "zebra"
@ -39,7 +38,7 @@ except OSError:
sys.exit(1) sys.exit(1)
class ManetNode(nodes.LxcNode): class ManetNode(core.nodes.base.CoreNode):
""" An Lxc namespace node configured for Quagga OSPFv3 MANET MDR """ An Lxc namespace node configured for Quagga OSPFv3 MANET MDR
""" """
conftemp = Template("""\ conftemp = Template("""\
@ -69,7 +68,7 @@ ip forwarding
routerid = ipaddr.split("/")[0] routerid = ipaddr.split("/")[0]
self.ipaddr = ipaddr self.ipaddr = ipaddr
self.routerid = routerid self.routerid = routerid
nodes.LxcNode.__init__(self, core, _id, name, nodedir) core.nodes.base.CoreBaseNode.__init__(self, core, _id, name, nodedir)
self.privatedir(self.confdir) self.privatedir(self.confdir)
self.privatedir(QUAGGA_STATE_DIR) self.privatedir(QUAGGA_STATE_DIR)
@ -243,10 +242,10 @@ class ManetExperiment(object):
prefix = ipaddress.Ipv4Prefix("10.14.0.0/16") prefix = ipaddress.Ipv4Prefix("10.14.0.0/16")
self.session = Session(1) self.session = Session(1)
# emulated network # emulated network
self.net = self.session.add_object(cls=nodes.WlanNode) self.net = self.session.create_node(cls=core.nodes.network.WlanNode)
for i in xrange(1, numnodes + 1): for i in xrange(1, numnodes + 1):
addr = "%s/%s" % (prefix.addr(i), 32) addr = "%s/%s" % (prefix.addr(i), 32)
tmp = self.session.add_object(cls=ManetNode, ipaddr=addr, _id="%d" % i, name="n%d" % i) tmp = self.session.create_node(cls=ManetNode, ipaddr=addr, _id="%d" % i, name="n%d" % i)
tmp.newnetif(self.net, [addr]) tmp.newnetif(self.net, [addr])
self.nodes.append(tmp) self.nodes.append(tmp)
# connect nodes with probability linkprob # connect nodes with probability linkprob

View file

@ -37,13 +37,14 @@ import os
import sys import sys
import time import time
import core.nodes.base
import core.nodes.network
from core import emane from core import emane
from core.emane.bypass import EmaneBypassModel from core.emane.bypass import EmaneBypassModel
from core.emane.nodes import EmaneNode from core.emane.nodes import EmaneNode
from core.emane.rfpipe import EmaneRfPipeModel from core.emane.rfpipe import EmaneRfPipeModel
from core.misc import ipaddress from core.nodes import ipaddress
from core.netns import nodes from core.emulator.session import Session
from core.session import Session
try: try:
import emaneeventservice import emaneeventservice
@ -413,11 +414,11 @@ class Experiment(object):
prefix = ipaddress.Ipv4Prefix("10.0.0.0/16") prefix = ipaddress.Ipv4Prefix("10.0.0.0/16")
self.session = Session(1) self.session = Session(1)
# emulated network # emulated network
self.net = self.session.add_object(cls=nodes.WlanNode, name="wlan1") self.net = self.session.create_node(cls=core.nodes.network.WlanNode, name="wlan1")
prev = None prev = None
for i in xrange(1, numnodes + 1): for i in xrange(1, numnodes + 1):
addr = "%s/%s" % (prefix.addr(i), 32) addr = "%s/%s" % (prefix.addr(i), 32)
tmp = self.session.add_object(cls=nodes.CoreNode, _id=i, name="n%d" % i) tmp = self.session.create_node(cls=core.nodes.base.CoreNode, _id=i, name="n%d" % i)
tmp.newnetif(self.net, [addr]) tmp.newnetif(self.net, [addr])
self.nodes.append(tmp) self.nodes.append(tmp)
self.session.services.add_services(tmp, "router", "IPForward") self.session.services.add_services(tmp, "router", "IPForward")
@ -440,12 +441,12 @@ class Experiment(object):
self.session.location.setrefgeo(47.57917, -122.13232, 2.00000) self.session.location.setrefgeo(47.57917, -122.13232, 2.00000)
self.session.location.refscale = 150.0 self.session.location.refscale = 150.0
self.session.emane.loadmodels() self.session.emane.loadmodels()
self.net = self.session.add_object(cls=EmaneNode, _id=numnodes + 1, name="wlan1") self.net = self.session.create_node(cls=EmaneNode, _id=numnodes + 1, name="wlan1")
self.net.verbose = verbose self.net.verbose = verbose
# self.session.emane.addobj(self.net) # self.session.emane.addobj(self.net)
for i in xrange(1, numnodes + 1): for i in xrange(1, numnodes + 1):
addr = "%s/%s" % (prefix.addr(i), 32) addr = "%s/%s" % (prefix.addr(i), 32)
tmp = self.session.add_object(cls=nodes.CoreNode, _id=i, name="n%d" % i) tmp = self.session.create_node(cls=core.nodes.base.CoreNode, _id=i, name="n%d" % i)
# tmp.setposition(i * 20, 50, None) # tmp.setposition(i * 20, 50, None)
tmp.setposition(50, 50, None) tmp.setposition(50, 50, None)
tmp.newnetif(self.net, [addr]) tmp.newnetif(self.net, [addr])

View file

@ -8,8 +8,8 @@
import optparse import optparse
import socket import socket
from core.api import coreapi from core.api.tlv import coreapi
from core.enumerations import MessageFlags, SessionTlvs, CORE_API_PORT from core.emulator.enumerations import MessageFlags, SessionTlvs, CORE_API_PORT
def main(): def main():

View file

@ -1,5 +1,5 @@
all: all:
$(PYTHON) -m grpc_tools.protoc -I . --python_out=../core/grpc --grpc_python_out=../core/grpc core.proto $(PYTHON) -m grpc_tools.protoc -I . --python_out=../core/api/grpc --grpc_python_out=../core/api/grpc core.proto
clean: clean:
-rm -f ../core/grpc/core_pb2* -rm -f ../core/api/grpc/core_pb2*

View file

@ -14,11 +14,11 @@ import time
from core import load_logging_config from core import load_logging_config
from core import constants from core import constants
from core import enumerations from core.emulator import enumerations
from core.corehandlers import CoreHandler from core.api.tlv.corehandlers import CoreHandler
from core.coreserver import CoreServer from core.api.tlv.coreserver import CoreServer
from core.grpc.server import CoreGrpcServer from core.api.grpc.server import CoreGrpcServer
from core.misc.utils import close_onexec from core.utils import close_onexec
load_logging_config() load_logging_config()
@ -48,7 +48,7 @@ def cored(cfg):
try: try:
server = CoreServer((host, port), CoreHandler, cfg) server = CoreServer((host, port), CoreHandler, cfg)
if cfg["ovs"] == "True": if cfg["ovs"] == "True":
from core.netns.openvswitch import OVS_NODES from core.nodes.openvswitch import OVS_NODES
server.coreemu.update_nodes(OVS_NODES) server.coreemu.update_nodes(OVS_NODES)
except: except:
logging.exception("error starting main server on: %s:%s", host, port) logging.exception("error starting main server on: %s:%s", host, port)

View file

@ -8,11 +8,11 @@ import os
import socket import socket
import sys import sys
from core.api import coreapi from core.api.tlv import coreapi
from core.enumerations import CORE_API_PORT from core.emulator.enumerations import CORE_API_PORT
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.enumerations import SessionTlvs from core.emulator.enumerations import SessionTlvs
def print_available_tlvs(t, tlv_class): def print_available_tlvs(t, tlv_class):

View file

@ -9,30 +9,30 @@ import time
import pytest import pytest
from mock.mock import MagicMock from mock.mock import MagicMock
from core.api.coreapi import CoreConfMessage from core.api.tlv.coreapi import CoreConfMessage
from core.api.coreapi import CoreEventMessage from core.api.tlv.coreapi import CoreEventMessage
from core.api.coreapi import CoreExecMessage from core.api.tlv.coreapi import CoreExecMessage
from core.api.coreapi import CoreLinkMessage from core.api.tlv.coreapi import CoreLinkMessage
from core.api.coreapi import CoreNodeMessage from core.api.tlv.coreapi import CoreNodeMessage
from core.corehandlers import CoreHandler from core.api.tlv.corehandlers import CoreHandler
from core.coreserver import CoreServer from core.api.tlv.coreserver import CoreServer
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes from core.emulator.emudata import IpPrefixes
from core.enumerations import CORE_API_PORT from core.emulator.enumerations import CORE_API_PORT
from core.enumerations import ConfigTlvs from core.emulator.enumerations import ConfigTlvs
from core.enumerations import EventTlvs from core.emulator.enumerations import EventTlvs
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import LinkTlvs
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import NodeTlvs from core.emulator.enumerations import NodeTlvs
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.grpc.client import InterfaceHelper from core.api.grpc.client import InterfaceHelper
from core.grpc.server import CoreGrpcServer from core.api.grpc.server import CoreGrpcServer
from core.misc import ipaddress from core.nodes import ipaddress
from core.misc.ipaddress import MacAddress from core.nodes.ipaddress import MacAddress
from core.service import ServiceManager from core.services.coreservices import ServiceManager
EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward" EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward"

View file

@ -4,12 +4,12 @@ Unit tests for testing CORE with distributed networks.
import conftest import conftest
from core.api.coreapi import CoreExecMessage from core.api.tlv.coreapi import CoreExecMessage
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc.ipaddress import IpAddress from core.nodes.ipaddress import IpAddress
def validate_response(replies, _): def validate_response(replies, _):
@ -89,7 +89,7 @@ class TestDistributed:
cored.request_handler.handle_message(message) cored.request_handler.handle_message(message)
# test a ping command # test a ping command
node_one = cored.session.get_object(1) node_one = cored.session.get_node(1)
message = conftest.command_message(node_one, "ping -c 5 %s" % ip4_address) message = conftest.command_message(node_one, "ping -c 5 %s" % ip4_address)
cored.request_handler.dispatch_replies = validate_response cored.request_handler.dispatch_replies = validate_response
cored.request_handler.handle_message(message) cored.request_handler.handle_message(message)
@ -155,7 +155,7 @@ class TestDistributed:
cored.request_handler.handle_message(message) cored.request_handler.handle_message(message)
# test a ping command # test a ping command
node_one = cored.session.get_object(1) node_one = cored.session.get_node(1)
message = conftest.command_message(node_one, "ping -c 5 %s" % ip4_address) message = conftest.command_message(node_one, "ping -c 5 %s" % ip4_address)
cored.request_handler.dispatch_replies = validate_response cored.request_handler.dispatch_replies = validate_response
cored.request_handler.handle_message(message) cored.request_handler.handle_message(message)

View file

@ -2,7 +2,7 @@
Sample user-defined services for testing. Sample user-defined services for testing.
""" """
from core.service import CoreService from core.services.coreservices import CoreService
class MyService(CoreService): class MyService(CoreService):

View file

@ -1,13 +1,13 @@
import pytest import pytest
from core.conf import ConfigurableManager from core.config import ConfigurableManager
from core.conf import ConfigurableOptions from core.config import ConfigurableOptions
from core.conf import Configuration from core.config import Configuration
from core.conf import ModelManager from core.config import ModelManager
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
class TestConfigurableOptions(ConfigurableOptions): class TestConfigurableOptions(ConfigurableOptions):

View file

@ -10,11 +10,11 @@ import pytest
from mock import MagicMock from mock import MagicMock
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
from core.mobility import Ns2ScriptedMobility from core.location.mobility import Ns2ScriptedMobility
from core.netns.vnodeclient import VnodeClient from core.nodes.client import VnodeClient
_PATH = os.path.abspath(os.path.dirname(__file__)) _PATH = os.path.abspath(os.path.dirname(__file__))
_MOBILITY_FILE = os.path.join(_PATH, "mobility.scen") _MOBILITY_FILE = os.path.join(_PATH, "mobility.scen")

View file

@ -5,13 +5,13 @@ from Queue import Queue
import grpc import grpc
import pytest import pytest
from core.conf import ConfigShim from core.config import ConfigShim
from core.data import EventData from core.emulator.data import EventData
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.enumerations import NodeTypes, EventTypes, ConfigFlags, ExceptionLevels from core.emulator.enumerations import NodeTypes, EventTypes, ConfigFlags, ExceptionLevels
from core.grpc import core_pb2 from core.api.grpc import core_pb2
from core.grpc.client import CoreGrpcClient from core.api.grpc.client import CoreGrpcClient
from core.mobility import BasicRangeModel, Ns2ScriptedMobility from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
class TestGrpc: class TestGrpc:
@ -182,7 +182,7 @@ class TestGrpc:
# then # then
assert response.id is not None assert response.id is not None
assert session.get_object(response.id) is not None assert session.get_node(response.id) is not None
def test_get_node(self, grpc_server): def test_get_node(self, grpc_server):
# given # given
@ -237,7 +237,7 @@ class TestGrpc:
assert response.result is expected assert response.result is expected
if expected is True: if expected is True:
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert session.get_object(node.id) assert session.get_node(node.id)
def test_get_hooks(self, grpc_server): def test_get_hooks(self, grpc_server):
# given # given
@ -390,8 +390,8 @@ class TestGrpc:
interface_two = ip_prefixes.create_interface(node_two) interface_two = ip_prefixes.create_interface(node_two)
session.add_link(node_one.id, node_two.id, interface_one, interface_two) session.add_link(node_one.id, node_two.id, interface_one, interface_two)
link_node = None link_node = None
for node_id in session.objects: for node_id in session.nodes:
node = session.objects[node_id] node = session.nodes[node_id]
if node.id not in {node_one.id, node_two.id}: if node.id not in {node_one.id, node_two.id}:
link_node = node link_node = node
break break

View file

@ -4,17 +4,17 @@ Unit tests for testing with a CORE switch.
import threading import threading
from core.api import coreapi, dataconversion from core.api.tlv import coreapi, dataconversion
from core.api.coreapi import CoreExecuteTlv from core.api.tlv.coreapi import CoreExecuteTlv
from core.enumerations import CORE_API_PORT, NodeTypes from core.emulator.enumerations import CORE_API_PORT, NodeTypes
from core.enumerations import EventTlvs from core.emulator.enumerations import EventTlvs
from core.enumerations import EventTypes from core.emulator.enumerations import EventTypes
from core.enumerations import ExecuteTlvs from core.emulator.enumerations import ExecuteTlvs
from core.enumerations import LinkTlvs from core.emulator.enumerations import LinkTlvs
from core.enumerations import LinkTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import MessageFlags from core.emulator.enumerations import MessageFlags
from core.enumerations import MessageTypes from core.emulator.enumerations import MessageTypes
from core.misc import ipaddress from core.nodes import ipaddress
def command_message(node, command): def command_message(node, command):

View file

@ -1,6 +1,6 @@
from core.emulator.emudata import LinkOptions from core.emulator.emudata import LinkOptions
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import utils from core import utils
def create_ptp_network(session, ip_prefixes): def create_ptp_network(session, ip_prefixes):

View file

@ -4,8 +4,8 @@ import time
import pytest import pytest
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.misc import utils from core import utils
MODELS = [ MODELS = [
"router", "router",
@ -63,7 +63,7 @@ class TestNodes:
# then # then
with pytest.raises(KeyError): with pytest.raises(KeyError):
session.get_object(node.id) session.get_node(node.id)
@pytest.mark.parametrize("net_type", NET_TYPES) @pytest.mark.parametrize("net_type", NET_TYPES)
def test_net(self, session, net_type): def test_net(self, session, net_type):

View file

@ -2,9 +2,9 @@ import os
import pytest import pytest
from core.service import CoreService from core.services.coreservices import CoreService
from core.service import ServiceDependencies from core.services.coreservices import ServiceDependencies
from core.service import ServiceManager from core.services.coreservices import ServiceManager
_PATH = os.path.abspath(os.path.dirname(__file__)) _PATH = os.path.abspath(os.path.dirname(__file__))
_SERVICES_PATH = os.path.join(_PATH, "myservices") _SERVICES_PATH = os.path.join(_PATH, "myservices")

View file

@ -1,4 +1,4 @@
from core.misc import utils from core import utils
class TestUtils: class TestUtils:

View file

@ -4,8 +4,8 @@ import pytest
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.emudata import NodeOptions from core.emulator.emudata import NodeOptions
from core.enumerations import NodeTypes from core.emulator.enumerations import NodeTypes
from core.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
from core.services.utility import SshService from core.services.utility import SshService
@ -87,16 +87,16 @@ class TestXml:
# verify nodes have been removed from session # verify nodes have been removed from session
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n1_id) assert not session.get_node(n1_id)
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n2_id) assert not session.get_node(n2_id)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(file_path, start=True)
# verify nodes have been recreated # verify nodes have been recreated
assert session.get_object(n1_id) assert session.get_node(n1_id)
assert session.get_object(n2_id) assert session.get_node(n2_id)
def test_xml_ptp_services(self, session, tmpdir, ip_prefixes): def test_xml_ptp_services(self, session, tmpdir, ip_prefixes):
""" """
@ -147,9 +147,9 @@ class TestXml:
# verify nodes have been removed from session # verify nodes have been removed from session
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n1_id) assert not session.get_node(n1_id)
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n2_id) assert not session.get_node(n2_id)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(file_path, start=True)
@ -158,8 +158,8 @@ class TestXml:
service = session.services.get_service(node_one.id, SshService.name) service = session.services.get_service(node_one.id, SshService.name)
# verify nodes have been recreated # verify nodes have been recreated
assert session.get_object(n1_id) assert session.get_node(n1_id)
assert session.get_object(n2_id) assert session.get_node(n2_id)
assert service.config_data.get(service_file) == file_data assert service.config_data.get(service_file) == file_data
def test_xml_mobility(self, session, tmpdir, ip_prefixes): def test_xml_mobility(self, session, tmpdir, ip_prefixes):
@ -208,9 +208,9 @@ class TestXml:
# verify nodes have been removed from session # verify nodes have been removed from session
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n1_id) assert not session.get_node(n1_id)
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n2_id) assert not session.get_node(n2_id)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(file_path, start=True)
@ -219,9 +219,9 @@ class TestXml:
value = str(session.mobility.get_config("test", wlan_id, BasicRangeModel.name)) value = str(session.mobility.get_config("test", wlan_id, BasicRangeModel.name))
# verify nodes and configuration were restored # verify nodes and configuration were restored
assert session.get_object(n1_id) assert session.get_node(n1_id)
assert session.get_object(n2_id) assert session.get_node(n2_id)
assert session.get_object(wlan_id) assert session.get_node(wlan_id)
assert value == "1" assert value == "1"
def test_xml_emane(self, session, tmpdir, ip_prefixes): def test_xml_emane(self, session, tmpdir, ip_prefixes):
@ -275,9 +275,9 @@ class TestXml:
# verify nodes have been removed from session # verify nodes have been removed from session
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n1_id) assert not session.get_node(n1_id)
with pytest.raises(KeyError): with pytest.raises(KeyError):
assert not session.get_object(n2_id) assert not session.get_node(n2_id)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(file_path, start=True)
@ -286,7 +286,7 @@ class TestXml:
value = str(session.emane.get_config("test", emane_id, EmaneIeee80211abgModel.name)) value = str(session.emane.get_config("test", emane_id, EmaneIeee80211abgModel.name))
# verify nodes and configuration were restored # verify nodes and configuration were restored
assert session.get_object(n1_id) assert session.get_node(n1_id)
assert session.get_object(n2_id) assert session.get_node(n2_id)
assert session.get_object(emane_id) assert session.get_node(emane_id)
assert value == "1" assert value == "1"

View file

@ -17,14 +17,13 @@ import ns.wifi
import ns.wimax import ns.wimax
from core import constants from core import constants
from core.coreobj import PyCoreNet from core.emulator.enumerations import EventTypes
from core.enumerations import EventTypes from core.emulator.enumerations import LinkTypes
from core.enumerations import LinkTypes from core.emulator.enumerations import NodeTypes
from core.enumerations import NodeTypes from core.utils import make_tuple
from core.misc.utils import make_tuple from core.location.mobility import WayPointMobility
from core.mobility import WayPointMobility from core.nodes.base import CoreNode, CoreNetworkBase
from core.netns.nodes import CoreNode from core.emulator.session import Session
from core.session import Session
ns.core.GlobalValue.Bind( ns.core.GlobalValue.Bind(
"SimulatorImplementationType", "SimulatorImplementationType",
@ -107,7 +106,7 @@ class CoreNs3Node(CoreNode, ns.network.Node):
self.warn("ns-3 mobility model not found, not setting position") self.warn("ns-3 mobility model not found, not setting position")
class CoreNs3Net(PyCoreNet): class CoreNs3Net(CoreNetworkBase):
""" """
The CoreNs3Net is a helper PyCoreNet object. Networks are represented The CoreNs3Net is a helper PyCoreNet object. Networks are represented
entirely in simulation with the TunTap device bridging the emulated and entirely in simulation with the TunTap device bridging the emulated and
@ -119,7 +118,7 @@ class CoreNs3Net(PyCoreNet):
type = "wlan" type = "wlan"
def __init__(self, session, _id=None, name=None, start=True, policy=None): def __init__(self, session, _id=None, name=None, start=True, policy=None):
PyCoreNet.__init__(self, session, _id, name) CoreNetworkBase.__init__(self, session, _id, name)
self.tapbridge = ns.tap_bridge.TapBridgeHelper() self.tapbridge = ns.tap_bridge.TapBridgeHelper()
self._ns3devs = {} self._ns3devs = {}
self._tapdevs = {} self._tapdevs = {}
@ -402,7 +401,7 @@ class Ns3Session(Session):
A convenience helper for Session.addobj(), for adding CoreNs3Nodes A convenience helper for Session.addobj(), for adding CoreNs3Nodes
to this session. Keeps a NodeContainer for later use. to this session. Keeps a NodeContainer for later use.
""" """
n = self.add_object(cls=CoreNs3Node, name=name) n = self.create_node(cls=CoreNs3Node, name=name)
self.nodes.Add(n) self.nodes.Add(n)
return n return n
@ -488,7 +487,7 @@ class Ns3Session(Session):
Start a tracing thread using the ASCII output from the ns3 Start a tracing thread using the ASCII output from the ns3
mobility helper. mobility helper.
""" """
net.mobility = WayPointMobility(session=self, object_id=net.id) net.mobility = WayPointMobility(session=self, _id=net.id)
net.mobility.setendtime() net.mobility.setendtime()
net.mobility.refresh_ms = 300 net.mobility.refresh_ms = 300
net.mobility.empty_queue_stop = False net.mobility.empty_queue_stop = False

View file

@ -11,9 +11,7 @@ import sys
import ns.core import ns.core
import ns.mobility import ns.mobility
from core.misc import ipaddress from core.nodes import nodeutils, nodemaps, ipaddress
from core.misc import nodemaps
from core.misc import nodeutils
from corens3.obj import Ns3LteNet from corens3.obj import Ns3LteNet
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
@ -24,7 +22,7 @@ def ltesession(opt):
""" """
nodeutils.set_node_map(nodemaps.NODES) nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
lte = session.add_object(cls=Ns3LteNet, name="wlan1") lte = session.create_node(cls=Ns3LteNet, name="wlan1")
lte.setsubchannels(range(25), range(50, 100)) lte.setsubchannels(range(25), range(50, 100))
if opt.verbose: if opt.verbose:
ascii_helper = ns.network.AsciiTraceHelper() ascii_helper = ns.network.AsciiTraceHelper()

View file

@ -28,9 +28,7 @@ import sys
import ns.core import ns.core
from core.misc import ipaddress from core.nodes import nodeutils, nodemaps, ipaddress
from core.misc import nodeutils
from core.misc import nodemaps
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WifiNet from corens3.obj import Ns3WifiNet
@ -59,7 +57,7 @@ def wifisession(opt):
session.node_count = str(opt.numnodes + 1) session.node_count = str(opt.numnodes + 1)
add_to_server(session) add_to_server(session)
wifi = session.add_object(cls=Ns3WifiNet, name="wlan1") wifi = session.create_node(cls=Ns3WifiNet, name="wlan1")
wifi.setposition(30, 30, 0) wifi.setposition(30, 30, 0)
wifi.phy.Set("RxGain", ns.core.DoubleValue(18.0)) wifi.phy.Set("RxGain", ns.core.DoubleValue(18.0))

View file

@ -20,9 +20,7 @@ import ns.network
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WifiNet from corens3.obj import Ns3WifiNet
from core.misc import ipaddress from core.nodes import nodeutils, nodemaps, ipaddress
from core.misc import nodemaps
from core.misc import nodeutils
def add_to_server(session): def add_to_server(session):
@ -48,7 +46,7 @@ def wifisession(opt):
session.filename = session.name + ".py" session.filename = session.name + ".py"
session.node_count = str(opt.numnodes + 1) session.node_count = str(opt.numnodes + 1)
add_to_server(session) add_to_server(session)
wifi = session.add_object(cls=Ns3WifiNet, name="wlan1", rate="OfdmRate12Mbps") wifi = session.create_node(cls=Ns3WifiNet, name="wlan1", rate="OfdmRate12Mbps")
wifi.setposition(30, 30, 0) wifi.setposition(30, 30, 0)
# for improved connectivity # for improved connectivity
wifi.phy.Set("RxGain", ns.core.DoubleValue(18.0)) wifi.phy.Set("RxGain", ns.core.DoubleValue(18.0))

View file

@ -13,9 +13,7 @@ import logging
import optparse import optparse
import sys import sys
from core.misc import ipaddress from core.nodes import nodeutils, nodemaps, ipaddress
from core.misc import nodemaps
from core.misc import nodeutils
from corens3.obj import Ns3Session from corens3.obj import Ns3Session
from corens3.obj import Ns3WimaxNet from corens3.obj import Ns3WimaxNet
@ -26,7 +24,7 @@ def wimaxsession(opt):
""" """
nodeutils.set_node_map(nodemaps.NODES) nodeutils.set_node_map(nodemaps.NODES)
session = Ns3Session(1, persistent=True, duration=opt.duration) session = Ns3Session(1, persistent=True, duration=opt.duration)
wimax = session.add_object(cls=Ns3WimaxNet, name="wlan1") wimax = session.create_node(cls=Ns3WimaxNet, name="wlan1")
# wimax.wimax.EnableLogComponents() # wimax.wimax.EnableLogComponents()
prefix = ipaddress.Ipv4Prefix("10.0.0.0/16") prefix = ipaddress.Ipv4Prefix("10.0.0.0/16")