Skip to content

Commit

Permalink
Merge pull request #676 from coreemu/develop
Browse files Browse the repository at this point in the history
Develop merge for 8.2.0
  • Loading branch information
bharnden authored Mar 22, 2022
2 parents bcf7429 + d7b2c3c commit 1841fb1
Show file tree
Hide file tree
Showing 32 changed files with 611 additions and 707 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 2022-03-21 CORE 8.2.0

* core-gui
* improved failed starts to trigger runtime to allow node investigation
* core-daemon
* improved default service loading to use a full import path
* updated session instantiation to always set to a runtime state
* core-cli
* \#672 - fixed xml loading
* \#578 - restored json flag and added geo output to session overview
* Documentation
* updated emane example and documentation
* improved table markdown

## 2022-02-18 CORE 8.1.0

* Installation
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ source ~/.bashrc
# Ubuntu
inv install
# CentOS
./install.sh -p /usr
inv install -p /usr
```

## Documentation & Support
Expand Down
2 changes: 1 addition & 1 deletion 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, 8.1.0)
AC_INIT(core, 8.2.0)

# autoconf and automake initialization
AC_CONFIG_SRCDIR([netns/version.h.in])
Expand Down
9 changes: 9 additions & 0 deletions daemon/core/api/grpc/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,15 @@ def from_proto(cls, proto: core_pb2.SessionSummary) -> "SessionSummary":
dir=proto.dir,
)

def to_proto(self) -> core_pb2.SessionSummary:
return core_pb2.SessionSummary(
id=self.id,
state=self.state.value,
nodes=self.nodes,
file=self.file,
dir=self.dir,
)


@dataclass
class Hook:
Expand Down
28 changes: 22 additions & 6 deletions daemon/core/configservice/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class ConfigServiceBootError(Exception):
pass


class ConfigServiceTemplateError(Exception):
pass


@dataclass
class ShadowDir:
path: str
Expand Down Expand Up @@ -316,7 +320,13 @@ def get_templates(self) -> Dict[str, str]:
elif self.templates.has_template(template_path):
template = self.templates.get_template(template_path).source
else:
template = self.get_text_template(file)
try:
template = self.get_text_template(file)
except Exception as e:
raise ConfigServiceTemplateError(
f"node({self.node.name}) service({self.name}) file({file}) "
f"failure getting template: {e}"
)
template = self.clean_text(template)
templates[file] = template
return templates
Expand All @@ -340,7 +350,13 @@ def create_files(self) -> None:
elif self.templates.has_template(template_path):
rendered = self.render_template(template_path, data)
else:
text = self.get_text_template(file)
try:
text = self.get_text_template(file)
except Exception as e:
raise ConfigServiceTemplateError(
f"node({self.node.name}) service({self.name}) file({file}) "
f"failure getting template: {e}"
)
rendered = self.render_text(text, data)
self.node.create_file(file_path, rendered)

Expand Down Expand Up @@ -429,20 +445,20 @@ def render_text(self, text: str, data: Dict[str, Any] = None) -> str:
f"{exceptions.text_error_template().render_unicode()}"
)

def render_template(self, basename: str, data: Dict[str, Any] = None) -> str:
def render_template(self, template_path: str, data: Dict[str, Any] = None) -> str:
"""
Renders file based template providing all associated data to template.
:param basename: base name for file to render
:param template_path: path of file to render
:param data: service specific defined data for template
:return: rendered template
"""
try:
template = self.templates.get_template(basename)
template = self.templates.get_template(template_path)
return self._render(template, data)
except Exception:
raise CoreError(
f"node({self.node.name}) service({self.name}) "
f"node({self.node.name}) service({self.name}) file({template_path})"
f"{exceptions.text_error_template().render_template()}"
)

Expand Down
3 changes: 1 addition & 2 deletions daemon/core/emulator/coreemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from pathlib import Path
from typing import Dict, List, Type

import core.services
from core import utils
from core.configservice.manager import ConfigServiceManager
from core.emane.modelmanager import EmaneModelManager
Expand Down Expand Up @@ -92,7 +91,7 @@ def _load_services(self) -> None:
:return: nothing
"""
# load default services
self.service_errors = core.services.load()
self.service_errors = ServiceManager.load_locals()
# load custom services
service_paths = self.config.get("custom_services_dir")
logger.debug("custom service paths: %s", service_paths)
Expand Down
46 changes: 12 additions & 34 deletions daemon/core/emulator/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,11 @@ def add_hook(
self.run_hook(hook)

def add_node_file(
self, node_id: int, src_path: Path, file_path: Path, data: str
self,
node_id: int,
src_path: Optional[Path],
file_path: Path,
data: Optional[str],
) -> None:
"""
Add a file to a node.
Expand All @@ -707,7 +711,7 @@ def add_node_file(
"""
node = self.get_node(node_id, CoreNode)
if src_path is not None:
node.addfile(src_path, file_path)
node.copy_file(src_path, file_path)
elif data is not None:
node.create_file(file_path, data)

Expand Down Expand Up @@ -1173,34 +1177,30 @@ def instantiate(self) -> List[Exception]:
:return: list of service boot errors during startup
"""
if self.state == EventTypes.RUNTIME_STATE:
logger.warning("ignoring instantiate, already in runtime state")
return []
# write current nodes out to session directory file
self.write_nodes()

# create control net interfaces and network tunnels
# which need to exist for emane to sync on location events
# in distributed scenarios
self.add_remove_control_net(0, remove=False)

# initialize distributed tunnels
self.distributed.start()

# instantiate will be invoked again upon emane configure
if self.emane.startup() == EmaneState.NOT_READY:
return []

# boot node services and then start mobility
exceptions = self.boot_nodes()
if not exceptions:
self.mobility.startup()

# notify listeners that instantiation is complete
event = EventData(event_type=EventTypes.INSTANTIATION_COMPLETE)
self.broadcast_event(event)

# assume either all nodes have booted already, or there are some
# nodes on slave servers that will be booted and those servers will
# send a node status response message
self.check_runtime()
# startup event loop
self.event_loop.run()
self.set_state(EventTypes.RUNTIME_STATE, send_event=True)
return exceptions

def get_node_count(self) -> int:
Expand All @@ -1222,28 +1222,6 @@ def get_node_count(self) -> int:
count += 1
return count

def check_runtime(self) -> None:
"""
Check if we have entered the runtime state, that all nodes have been
started and the emulation is running. Start the event loop once we
have entered runtime (time=0).
:return: nothing
"""
# this is called from instantiate() after receiving an event message
# for the instantiation state
logger.debug(
"session(%s) checking if not in runtime state, current state: %s",
self.id,
self.state.name,
)
if self.state == EventTypes.RUNTIME_STATE:
logger.info("valid runtime state found, returning")
return
# start event loop and set to runtime
self.event_loop.run()
self.set_state(EventTypes.RUNTIME_STATE, send_event=True)

def data_collect(self) -> None:
"""
Tear down a running session. Stop the event loop and any running
Expand Down
2 changes: 1 addition & 1 deletion daemon/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CoreCommandError(subprocess.CalledProcessError):

def __str__(self) -> str:
return (
f"Command({self.cmd}), Status({self.returncode}):\n"
f"command({self.cmd}), status({self.returncode}):\n"
f"stdout: {self.output}\nstderr: {self.stderr}"
)

Expand Down
17 changes: 7 additions & 10 deletions daemon/core/gui/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,16 +304,13 @@ def click_start(self) -> None:
task.start()

def start_callback(self, result: bool, exceptions: List[str]) -> None:
if result:
self.set_runtime()
self.app.core.show_mobility_players()
else:
enable_buttons(self.design_frame, enabled=True)
if exceptions:
message = "\n".join(exceptions)
self.app.show_exception_data(
"Start Exception", "Session failed to start", message
)
self.set_runtime()
self.app.core.show_mobility_players()
if not result and exceptions:
message = "\n".join(exceptions)
self.app.show_exception_data(
"Start Exception", "Session failed to start", message
)

def set_runtime(self) -> None:
enable_buttons(self.runtime_frame, enabled=True)
Expand Down
Loading

0 comments on commit 1841fb1

Please sign in to comment.