Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8d15b2a
emane: fixed issue with tdma model code
bharnden Jul 30, 2024
c0c3cf5
docs: fixed missing sudo in ubuntu install example
bharnden Jul 30, 2024
44ff508
docs: updated tutorial documentation to refer to absolute paths of th…
bharnden Jul 30, 2024
d9013ab
updates to service documentation validation mode to use actual variab…
bharnden Aug 9, 2024
33f07dd
updated incorrect documentation for grpc client open xml
bharnden Aug 9, 2024
a1464a2
daemon: fixed service run validation to avoid crashing when more than…
bharnden Aug 9, 2024
c02f8e1
docs: update docker run example to include using --init for process c…
bharnden Aug 9, 2024
6ebda61
Merge branch 'develop' of https://github.com/coreemu/core into develop
bharnden Aug 9, 2024
e07e27c
docs: updated tutorial 3 to use absolute paths to scripts
bharnden Oct 8, 2024
8609480
grpc: fixed open xml start call to properly read and account for cont…
bharnden Oct 8, 2024
ff7c5c8
gui: fixed issue with changing an icon for link layer nodes
bharnden Oct 8, 2024
d17d7ad
docs: adjusted docker install run example to use absolute path
bharnden Dec 14, 2024
dc88d8e
docs: updated gRPC edit link example to start session properly before…
bharnden Dec 14, 2024
17de618
daemon: updated all services to use pkill instead of killall, which i…
bharnden Dec 14, 2024
1675688
examples: move example python case of configuring services to proper …
bharnden Dec 14, 2024
b3fe69c
daemon: fixed black formatting issue
bharnden Dec 14, 2024
a26b354
gRPC: added better documentation to make clear the usage of the Inter…
bharnden Dec 14, 2024
8df6b06
gui: when closing the app with a running session and cancel is select…
bharnden Dec 14, 2024
2234392
examples: updated interface creation to avoid using the helper to mak…
bharnden Dec 14, 2024
ad2d912
daemon: fixed issue deleting links related to ptp nodes, updated logg…
bharnden Dec 14, 2024
5fca949
bump version for next release to 9.2.0, updated various dependencies …
bharnden Feb 4, 2025
17b2862
update github workflow to use python3.12 and ubuntu 24
bharnden Feb 4, 2025
91ccfb4
daemon: fixed poetry lock file from recent changes
bharnden Feb 4, 2025
b747dfb
daemon: update version of flake8 used to avoid known issue
bharnden Feb 4, 2025
d18e643
updates to pytest version and unit tests to use the proper approach f…
bharnden Feb 5, 2025
dc49e37
updates to isort dev dependency
bharnden Feb 5, 2025
bdb55ed
update github workflow for isort
bharnden Feb 5, 2025
05bd350
fixed imports with updated isort and adjusted isort pre-commit command
bharnden Feb 5, 2025
7a5e42a
fixed isort deprecated flag syntax for updated isort version
bharnden Feb 5, 2025
44ca31f
removed unwanted dependency from built packages, update docker docs, …
bharnden Feb 11, 2025
0750f19
adjust github action for python3.10
bharnden Feb 11, 2025
af61850
fixed github action python version to a valid case
bharnden Feb 11, 2025
8f4bf53
bumped netaddr library to latest before major release
bharnden Feb 11, 2025
585a48f
adjust python code where possible to use updated Optional and Union t…
bharnden Feb 11, 2025
8070eaf
updated CHANGELOG and install related documentation
bharnden Feb 11, 2025
ca1e497
updated Dockerfiles for rocky/ubuntu, added build Dockerfile to creat…
bharnden Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/daemon-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.9
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.9
python-version: 3.10.16
- name: install poetry
run: |
python -m pip install --upgrade pip
Expand All @@ -22,15 +22,15 @@ jobs:
- name: isort
run: |
cd daemon
poetry run isort -c -df
poetry run isort -c --df .
- name: black
run: |
cd daemon
poetry run black --check .
- name: flake8
run: |
cd daemon
poetry run flake8
poetry run flake8 .
- name: grpc
run: |
cd daemon/proto
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## 2025-02-11 CORE 9.2.0

* Installation
* python3.10+ now required
* updated various dependencies to help avoid the need to build them from source
* Documentation
* docker run examples updated
* gRPC edit link examples corrected
* updated install examples
* updated tutorials to use absolute paths
* updated custom service example
* core-daemon
* removed use of killall in provided services
* \#860 - fixed core-cli xml --start to run control network
* \#881 - EMANE TDMA fails to start
* \#888 - fixed service start validation
* \#902 - link deletion removing incorrect nodes
* core-gui
* fixed bug when changing icons on a loaded scenario
* \#897 - fixed to properly exit when closing on a running session

## 2024-07-04 CORE 9.1.0

* Installation
Expand Down
2 changes: 0 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ fpm -s dir -t rpm -n core \
-d "tk" \
-d "procps-ng" \
-d "bash >= 3.0" \
-d "ebtables" \
-d "iproute" \
-d "libev" \
-d "net-tools" \
Expand Down Expand Up @@ -133,7 +132,6 @@ fpm -s dir -t deb -n core \
-d "procps" \
-d "libc6 >= 2.14" \
-d "bash >= 3.0" \
-d "ebtables" \
-d "iproute2" \
-d "libev4" \
-d "nftables" \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

CORE: Common Open Research Emulator

Copyright (c)2005-2023 the Boeing Company.
Copyright (c)2005-2025 the Boeing Company.

See the LICENSE file included in this distribution.

Expand Down
6 changes: 3 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.

# this defines the CORE version number, must be static for AC_INIT
AC_INIT(core, 9.1.0)
AC_INIT(core, 9.2.0)

# autoconf and automake initialization
AC_CONFIG_SRCDIR([netns/version.h.in])
Expand Down Expand Up @@ -79,8 +79,8 @@ if test "x$enable_daemon" = "xyes"; then
want_python=yes
want_linux_netns=yes

AM_PATH_PYTHON(3.9)
AS_IF([$PYTHON -m grpc_tools.protoc -h &> /dev/null], [], [AC_MSG_ERROR([please install python grpcio-tools])])
AM_PATH_PYTHON(3.10)
AS_IF([./venv/bin/python -m grpc_tools.protoc -h &> /dev/null], [], [AC_MSG_ERROR([grpc tools must be setup in venv, try setup.sh])])

AC_CHECK_PROG(sysctl_path, sysctl, $as_dir, no, $SEARCHPATH)
if test "x$sysctl_path" = "xno" ; then
Expand Down
10 changes: 5 additions & 5 deletions daemon/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ repos:
hooks:
- id: isort
name: isort
stages: [commit]
stages: [pre-commit]
language: system
entry: bash -c 'cd daemon && poetry run isort --atomic -y'
entry: bash -c 'cd daemon && poetry run isort --atomic .'
types: [python]

- id: black
name: black
stages: [commit]
stages: [pre-commit]
language: system
entry: bash -c 'cd daemon && poetry run black .'
types: [python]

- id: flake8
name: flake8
stages: [commit]
stages: [pre-commit]
language: system
entry: bash -c 'cd daemon && poetry run flake8'
entry: bash -c 'cd daemon && poetry run flake8 .'
types: [python]
36 changes: 19 additions & 17 deletions daemon/core/api/grpc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from contextlib import contextmanager
from pathlib import Path
from queue import Queue
from typing import Any, Optional
from typing import Any

import grpc

Expand Down Expand Up @@ -57,7 +57,7 @@
class MoveNodesStreamer:
def __init__(self, session_id: int, source: str = None) -> None:
self.session_id: int = session_id
self.source: Optional[str] = source
self.source: str | None = source
self.queue: SetQueue = SetQueue()

def send_position(self, node_id: int, x: float, y: float) -> None:
Expand All @@ -83,8 +83,8 @@ def send(self, request: wrappers.MoveNodesRequest) -> None:
def stop(self) -> None:
self.queue.put(None)

def next(self) -> Optional[core_pb2.MoveNodesRequest]:
request: Optional[wrappers.MoveNodesRequest] = self.queue.get()
def next(self) -> core_pb2.MoveNodesRequest | None:
request: wrappers.MoveNodesRequest | None = self.queue.get()
if request:
return request.to_proto()
else:
Expand All @@ -98,11 +98,11 @@ class EmanePathlossesStreamer:
def __init__(self) -> None:
self.queue: Queue = Queue()

def send(self, request: Optional[wrappers.EmanePathlossesRequest]) -> None:
def send(self, request: wrappers.EmanePathlossesRequest | None) -> None:
self.queue.put(request)

def next(self) -> Optional[emane_pb2.EmanePathlossesRequest]:
request: Optional[wrappers.EmanePathlossesRequest] = self.queue.get()
def next(self) -> emane_pb2.EmanePathlossesRequest | None:
request: wrappers.EmanePathlossesRequest | None = self.queue.get()
if request:
return request.to_proto()
else:
Expand All @@ -116,11 +116,11 @@ class EmaneEventsStreamer:
def __init__(self) -> None:
self.queue: Queue = Queue()

def send(self, request: Optional[wrappers.EmaneEventsRequest]) -> None:
def send(self, request: wrappers.EmaneEventsRequest | None) -> None:
self.queue.put(request)

def next(self) -> Optional[emane_pb2.EmaneEventsRequest]:
request: Optional[wrappers.EmaneEventsRequest] = self.queue.get()
def next(self) -> emane_pb2.EmaneEventsRequest | None:
request: wrappers.EmaneEventsRequest | None = self.queue.get()
if request:
return request.to_proto()
else:
Expand All @@ -133,6 +133,10 @@ def iter(self):
class InterfaceHelper:
"""
Convenience class to help generate IP4 and IP6 addresses for gRPC clients.

This is not a requirement to use, as interfaces can be created manually as
desired. Node IDs are used to index into a subnet, so if the subnet is tool small
of a pool of addresses and the node ID is too high, there will be a failure.
"""

def __init__(self, ip4_prefix: str = None, ip6_prefix: str = None) -> None:
Expand Down Expand Up @@ -242,8 +246,8 @@ def __init__(self, address: str = "localhost:50051", proxy: bool = False) -> Non
:param address: grpc server address to connect to
"""
self.address: str = address
self.stub: Optional[core_pb2_grpc.CoreApiStub] = None
self.channel: Optional[grpc.Channel] = None
self.stub: core_pb2_grpc.CoreApiStub | None = None
self.channel: grpc.Channel | None = None
self.proxy: bool = proxy

def start_session(
Expand Down Expand Up @@ -830,7 +834,7 @@ def open_xml(self, file_path: Path, start: bool = False) -> tuple[bool, int]:
Load a local scenario XML file to open as a new session.

:param file_path: path of scenario XML file
:param start: tuple of result and session id when successful
:param start: instantiate session if true, false for a definition state
:return: tuple of result and session id
"""
with file_path.open("r") as f:
Expand Down Expand Up @@ -934,7 +938,7 @@ def get_emane_event_channel(
response = self.stub.GetEmaneEventChannel(request)
return wrappers.EmaneEventChannel.from_proto(response)

def execute_script(self, script: str, args: str) -> Optional[int]:
def execute_script(self, script: str, args: str) -> int | None:
"""
Executes a python script given context of the current CoreEmu object.

Expand Down Expand Up @@ -1073,9 +1077,7 @@ def create_service(
recreate: bool = False,
) -> bool:
request = CreateServiceRequest(
service=service.to_proto(),
templates=templates,
recreate=recreate,
service=service.to_proto(), templates=templates, recreate=recreate
)
response = self.stub.CreateService(request)
return response.result
Expand Down
3 changes: 1 addition & 2 deletions daemon/core/api/grpc/events.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging
from collections.abc import Iterable
from queue import Empty, Queue
from typing import Optional

from core.api.grpc import core_pb2, grpcutils
from core.api.grpc.grpcutils import convert_link_data
Expand Down Expand Up @@ -113,7 +112,7 @@ def add_handlers(self) -> None:
if core_pb2.EventType.SESSION in self.event_types:
self.session.broadcast_manager.add_handler(EventData, self.queue.put)

def process(self) -> Optional[core_pb2.Event]:
def process(self) -> core_pb2.Event | None:
"""
Process the next event in the queue.

Expand Down
15 changes: 7 additions & 8 deletions daemon/core/api/grpc/grpcutils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import time
from pathlib import Path
from typing import Any, Optional, Union
from typing import Any

import grpc
from google.protobuf.internal.containers import RepeatedCompositeFieldContainer
Expand Down Expand Up @@ -248,7 +248,7 @@ def convert_session_options(session: Session) -> dict[str, common_pb2.ConfigOpti

def get_config_options(
config: dict[str, str],
configurable_options: Union[ConfigurableOptions, type[ConfigurableOptions]],
configurable_options: ConfigurableOptions | type[ConfigurableOptions],
) -> dict[str, common_pb2.ConfigOption]:
"""
Retrieve configuration options in a form that is used by the grpc server.
Expand Down Expand Up @@ -348,8 +348,7 @@ def get_node_proto(
if not service.custom_templates and not service.custom_config:
continue
service_configs[service.name] = services_pb2.ServiceConfig(
templates=service.custom_templates,
config=service.custom_config,
templates=service.custom_templates, config=service.custom_config
)
return core_pb2.Node(
id=node.id,
Expand Down Expand Up @@ -525,9 +524,9 @@ def convert_options_proto(options: core_pb2.LinkOptions) -> LinkOptions:

def convert_link(
node1: NodeBase,
iface1: Optional[CoreInterface],
iface1: CoreInterface | None,
node2: NodeBase,
iface2: Optional[CoreInterface],
iface2: CoreInterface | None,
options: LinkOptions,
unidirectional: bool,
) -> core_pb2.Link:
Expand Down Expand Up @@ -710,7 +709,7 @@ def get_hooks(session: Session) -> list[core_pb2.Hook]:

def get_mobility_node(
session: Session, node_id: int, context: ServicerContext
) -> Union[WlanNode, EmaneNet]:
) -> WlanNode | EmaneNet:
"""
Get mobility node.

Expand Down Expand Up @@ -820,5 +819,5 @@ def configure_node(
service.set_template(name, template)


def get_optional(message: Message, name: str) -> Optional[Any]:
def get_optional(message: Message, name: str) -> Any | None:
return getattr(message, name) if message.HasField(name) else None
21 changes: 5 additions & 16 deletions daemon/core/api/grpc/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from concurrent import futures
from pathlib import Path
from re import Pattern
from typing import Optional

import grpc
from grpc import ServicerContext
Expand Down Expand Up @@ -107,7 +106,7 @@ def __init__(self, coreemu: CoreEmu) -> None:
super().__init__()
self.coreemu: CoreEmu = coreemu
self.running: bool = True
self.server: Optional[grpc.Server] = None
self.server: grpc.Server | None = None
# catch signals
signal.signal(signal.SIGHUP, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
Expand Down Expand Up @@ -230,10 +229,7 @@ def GetConfig(
)
services.append(service_proto)
emane_models = [x.name for x in EmaneModelManager.models.values()]
return core_pb2.GetConfigResponse(
services=services,
emane_models=emane_models,
)
return core_pb2.GetConfigResponse(services=services, emane_models=emane_models)

def StartSession(
self, request: core_pb2.StartSessionRequest, context: ServicerContext
Expand Down Expand Up @@ -1305,9 +1301,7 @@ def GetWirelessConfig(
return GetWirelessConfigResponse(config=config_options)

def EmaneEvents(
self,
request_iterator: Iterable[EmaneEventsRequest],
context: ServicerContext,
self, request_iterator: Iterable[EmaneEventsRequest], context: ServicerContext
) -> EmaneEventsResponse:
for request in request_iterator:
session = self.get_session(request.session_id, context)
Expand Down Expand Up @@ -1396,10 +1390,7 @@ def EmaneEvents(
session, node, antenna.iface_id, context
)
session.emane.event_manager.publish_antenna_profile(
nem_id,
antenna.profile,
antenna.azimuth,
antenna.elevation,
nem_id, antenna.profile, antenna.azimuth, antenna.elevation
)
elif request.HasField("fading"):
fading = request.fading
Expand All @@ -1416,9 +1407,7 @@ def EmaneEvents(
return EmaneEventsResponse()

def CreateService(
self,
request: CreateServiceRequest,
context: ServicerContext,
self, request: CreateServiceRequest, context: ServicerContext
) -> CreateServiceResponse:
service = request.service
class_name = f"{service.name.capitalize()}Class"
Expand Down
Loading