diff --git a/.editorconfig b/.editorconfig index d0466b2f..f1b09263 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,7 @@ insert_final_newline = true [*.py] indent_style = space indent_size = 4 +max_line_length = 88 [*.am] indent_style = tab diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..6e3ab3c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. Ubuntu 18.04] + - CORE Version [e.g. 5.2.1] + - EMANE Version [e.g. 1.2.4] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..f4558654 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FEATURE]" +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/daemon-checks.yml b/.github/workflows/daemon-checks.yml new file mode 100644 index 00000000..dc169dcf --- /dev/null +++ b/.github/workflows/daemon-checks.yml @@ -0,0 +1,41 @@ +name: Daemon Checks + +on: [push] + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v1 + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + - name: install poetry + run: | + python -m pip install --upgrade pip + pip install poetry + cd daemon + cp core/constants.py.in core/constants.py + sed -i 's/required=True/required=False/g' core/emulator/coreemu.py + poetry install + - name: isort + run: | + cd daemon + poetry run isort -c -df + - name: black + run: | + cd daemon + poetry run black --check . + - name: flake8 + run: | + cd daemon + poetry run flake8 + - name: grpc + run: | + cd daemon/proto + poetry run python -m grpc_tools.protoc -I . --python_out=.. --grpc_python_out=.. core/api/grpc/*.proto + - name: test + run: | + cd daemon + poetry run pytest --mock tests diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 00000000..abbadab3 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,21 @@ +name: documentation +on: + push: + branches: + - master +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: actions/cache@v2 + with: + key: ${{ github.ref }} + path: .cache + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore index c59824e9..ca4c07dd 100644 --- a/.gitignore +++ b/.gitignore @@ -14,14 +14,22 @@ config.h.in config.log config.status configure +configure~ debian stamp-h1 -# python +# python virtual environments +venv + +# generated protobuf files +*_pb2.py +*_pb2_grpc.py + +# python build directory dist -*.egg-info -.cache -*.pyc + +# vscode +.vscode # intellij *.iml @@ -34,14 +42,26 @@ dist coverage.xml # python files +*.egg-info +*.pyc # ignore package files *.rpm *.deb *.tar.gz +# pytest cache files +.cache + # ignore swap files *.swp -# java files -target +# ignore built input files +netns/setup.py +daemon/setup.py + +# python +__pycache__ + +# ignore core player files +*.core diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..425f2ae0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,977 @@ +## 2023-08-01 CORE 9.0.3 + +* Installation + * updated various dependencies +* Documentation + * improved GUI docs to include node interaction and note xhost usage + * \#780 - fixed gRPC examples + * \#787 - complete documentation revamp to leverage mkdocs material + * \#790 - fixed custom emane model example +* core-daemon + * update type hinting to avoid deprecated imports + * updated commands ran within docker based nodes to have proper environment variables + * fixed issue improperly setting session options over gRPC + * \#668 - add fedora sbin path to frr service + * \#774 - fixed pcap configservice + * \#805 - fixed radvd configservice template error +* core-gui + * update type hinting to avoid deprecated imports + * fixed issue allowing duplicate named hook scripts + * fixed issue joining sessions with RJ45 nodes +* utility scripts + * fixed issue in core-cleanup for removing devices + +## 2023-03-02 CORE 9.0.2 + +* Installation + * updated python dependencies, including invoke to resolve python 3.10+ issues + * improved example dockerfiles to use less space for built images +* Documentation + * updated emane install instructions + * added Docker related issues to install instructions +* core-daemon + * fixed issue using invalid device name in sysctl commands + * updated PTP nodes to properly disable mac learning for their linux bridge + * fixed issue for LXC nodes to properly use a configured image name and write it to XML + * \#742 - fixed issue with bad wlan node id being used + * \#744 - fixed issue not properly setting broadcast address +* core-gui + * fixed sample1.xml to remove SSH service + * fixed emane demo examples + * fixed issue displaying emane configs generally configured for a node + +## 2022-11-28 CORE 9.0.1 + +* Installation + * updated protobuf and grpcio-tools versions in pyproject.toml to account for bad version mix + +## 2022-11-18 CORE 9.0.0 + +* Breaking Changes + * removed session nodes file + * removed session state file + * emane now runs in one process per nem with unique control ports + * grpc client has been refactored and updated + * removed tcl/legacy gui, imn file support and the tlv api + * link configuration is now different, but consistent, for wired links +* Installation + * added packaging for single file distribution + * python3.9 is now the minimum required version + * updated Dockerfile examples + * updated various python dependencies + * virtual environment is now installed to /opt/core/venv +* Documentation + * updated emane invoke task examples + * revamped install documentation + * added wireless node notes +* core-gui + * updated config services to display rendered templated and allow editing + * fixed node icon issue when updating preferences + * \#89 - throughput widget now works for hubs/switches + * \#691 - fixed custom nodes to properly use config services +* gRPC API + * add linked call to support linking and unlinking interfaces without destroying them + * fixed issue during start session clearing out session options + * added call to get rendered config service files + * removed get_node_links from links from client + * nem id and nem port have been added to GetNode and AddLink calls +* core-daemon + * wired links always create two veth pairs joined by a bridge + * node interfaces are now configured within the container to apply to outgoing traffic + * session.add_node now uses NodeOptions, allowing for node specific options + * fixed issue with xml reading node canvas values + * removed Session.add_node_file + * fixed get requirements logic + * fixed docker/lxd node support terminal commands on remote servers + * improved docker node command execution time using nsenter + * new wireless node type added to support dynamic loss based on distance + * \#513 - add and deleting distributed links during runtime is now supported + * \#703 - fixed issue not starting emane event listening service + +## 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 + * updated dependency versions to account for known vulnerabilities +* GUI + * fixed issue drawing asymmetric link configurations when joining a session +* daemon + * fixed issue getting templates and creating files for config services + * added by directional support for network to network links + * \#647 - fixed issue when creating RJ45 nodes + * \#646 - fixed issue when creating files for Docker nodes + * \#645 - improved wlan change updates to account for all updates with no delay +* services + * fixed file generation for OSPFv2 config service + +## 2022-01-12 CORE 8.0.0 + +*Breaking Changes + * heavily refactored gRPC client, removing some calls, adding others, all using type hinted classes representing their protobuf counterparts + * emane adjustments to run each nem in its own process, includes adjustments to configuration, which may cause issues + * internal daemon cleanup and refactoring, in a script directly driving a scenario is used +* Installation + * added options to allow installation without ospf mdr + * removed tasks that are no longer needed + * updates to properly install/remove example files + * pipx/poetry/invoke versions are now locked to help avoid update related issues + * install.sh is now setup.sh and is a convenience to get tool setup to run invoke +* Documentation + * formally added notes for Docker and LXD based node types + * added config services + * Updated README to have quick notes for installation + * \#563 - update to note how to enable core service +* Examples + * \#598 - update to fix sample1.imn to working order +* core-daemon + * emane global configuration is now configurable per nem + * fixed wlan loss to support float values + * improved default service loading to use full core path + * improved emane model loading to occur one time + * fixed handling rj45 link edits from tlv api + * fixed wlan config getting a default value for the promiscuous setting when not provided + * ebtables usage has now been replaced with nftables + * \#564 - logging is now using module named loggers + * \#573 - emane processes are not created 1 to 1 with nems + * \#608 - update lxml version + * \#609 - update pyyaml version + * \#623 - fixed issue with ovs mode and mac learning +* core-gui + * config services are now the default service type + * legacy services are marked as deprecated + * fix to properly load session options + * logging is now using module named loggers + * save as will not update the current session file name as expected + * fix to properly clear out removed customized services + * adding directories to a service that do not exist, is now valid + * added flag to exit after creating gui directory from command line + * added new options to enable/disable ip4/ip6 assignment + * improved canvas draw order, when joining sessions + * improved node copy/paste to avoid issues when pasting text into service config dialogs + * each canvas will not correctly save and load their size from xml +* gRPC API + * session options are now returned for GetSession + * fixed issue not properly creating the session directory during start session definition state + * updates to separate editing a node and moving a node, new MoveNode call added, EditNode is now used for editing icons +* Services + * fixed default route config service + * config services now have options for shadowing directories, including per node customization + +## 2021-09-17 CORE 7.5.2 + +* Installation + * \#596 - fixes issue related to installing poetry by pinning version to 1.1.7 + * updates pipx installation to pinned version 0.16.4 +* core-daemon + * \#600 - fixes known vulnerability for pillow dependency by updating version + +## 2021-04-15 CORE 7.5.1 + +* core-pygui + * fixed issues creating and drawing custom nodes + +## 2021-03-11 CORE 7.5.0 + +* core-daemon + * fixed issue setting mobility loop value properly + * fixed issue that some states would not properly remove session directories + * \#560 - fixed issues with sdt integration for mobility movement and layer creation +* core-pygui + * added multiple canvas support + * added support to hide nodes and restore them visually + * update to assign full netmasks to wireless connected nodes by default + * update to display services and action controls for nodes during runtime + * fixed issues with custom nodes + * fixed issue auto assigning macs, avoiding duplication + * fixed issue joining session with different netmasks + * fixed issues when deleting a session from the sessions dialog + * \#550 - fixed issue not sending all service customization data +* core-cli + * added delete session command + +## 2021-01-11 CORE 7.4.0 + +* Installation + * fixed issue for automated install assuming ID_LIKE is always present in /etc/os-release +* gRPC API + * fixed issue stopping session and not properly going to data collect state + * fixed issue to have start session properly create a directory before configuration state +* core-pygui + * fixed issue handling deletion of wired link to a switch + * avoid saving edge metadata to xml when values are default + * fixed issue editing node mac addresses + * added support for configuring interface names + * fixed issue with potential node names to allow hyphens and remove under bars + * \#531 - fixed issue changing distributed nodes back to local +* core-daemon + * fixed issue to properly handle deleting links from a network to network node + * updated xml to support writing and reading link buffer configurations + * reverted change and removed mac learning from wlan, due to promiscuous like behavior + * fixed issue creating control interfaces when starting services + * fixed deadlock issue when clearing a session using sdt + * \#116 - fixed issue for wlans handling multiple mobility scripts at once + * \#539 - fixed issue in udp tlv api + +## 2020-12-02 CORE 7.3.0 + +* core-daemon + * fixed issue where emane global configuration was not being sent to core-gui + * updated controlnet names on host to be prefixed with ctrl + * fixed RJ45 link shutdown from core-gui causing an error + * fixed emane external transport xml generation + * \#517 - update to account for radvd required directory + * \#514 - support added for session specific environment files + * \#529 - updated to configure netem limit based on delay or user specified, requires kernel 3.3+ +* core-pygui + * fixed issue drawing wlan/emane link options when it should not have + * edge labels are now placed a set distance from nodes like original gui + * link color/width are now saved to xml files + * added support to configure buffer size for links + * \#525 - added support for multiple wired links between the same nodes + * \#526 - added option to hide/show links with 100% loss +* Documentation + * \#527 - typo in service documentation + * \#515 - added examples to docs for using EMANE features within a CORE context + +## 2020-09-29 CORE 7.2.1 + +* core-daemon + * fixed issue where shutting down sessions may not have removed session directories + * fixed issue with multiple emane interfaces on the same node not getting the right configuration +* Installation + * updated automated install to be a bit more robust for alternative distros + * added force install type to try and leverage a redhat/debian like install + * locked ospf mdr version installed to older commit to avoid issues with multiple interfaces on same node + +## 2020-09-15 CORE 7.2.0 + +* Installation + * locked down version of ospf-mdr installed in automated install + * locked down version of emane to v1.2.5 in automated emane install + * added option to install locally using the -l option +* core-daemon + * improve error when retrieving services that do not exist, or failed to load + * fixed issue with writing/reading emane node interface configurations to xml + * fixed issue with not setting the emane model when creating a node + * added common utility method for getting a emane node interface config id in core.utils + * fixed issue running emane on more than one interface for a node + * fixed issue validating paths when creating emane transport xml for a node + * fixed issue avoiding multiple calls to shutdown, if already in shutdown state +* core-pygui + * fixed issue configuring emane for a node interface +* gRPC API + * added wrapper client that can provide type hinting and a simpler interface at core.api.grpc.clientw + * fixed issue creating sessions that default to having a very large reference scale + * fixed issue with GetSession returning control net nodes + +## 2020-08-21 CORE 7.1.0 + +* Installation + * added core-python script that gets installed to help globally reference the virtual environment +* gRPC API + * GetSession will now return all configuration information for a session and the file it was opened from, if applicable + * node update events will now include icon information + * fixed issue with getting session throughputs for sessions with a high id +* core-daemon + * \#503 - EMANE networks will now work with mobility again + * \#506 - fixed service dependency resolution issue + * fixed issue sending hooks to core-gui when joining session +* core-pygui + * fixed issues editing hooks + * fixed issue with cpu usage when joining a session + * fixed mac field not being disabled during runtime when configuring a node + * removed unlimited button from link config dialog + * fixed issue with copy/paste links and their options + * fixed issue with adding nodes/links and editing links during runtime + * updated open file dialog in config dialogs to open to ~/.coregui home directory + * fixed issue double clicking sessions dialog in invalid areas + * added display of asymmetric link options on links + * fixed emane config dialog display + * fixed issue saving backgrounds in xml files + * added view toggle for wired/wireless links + * node events will now update icons + +## 2020-07-28 CORE 7.0.1 + +* Bugfixes + * \#500 - fixed issue running node commands with shell=True + * fixed issue for poetry based install not properly vetting requirements for dataclasses dependency + +## 2020-07-23 CORE 7.0.0 + +* Breaking Changes + * core.emudata and core.data combined and cleaned up into core.data + * updates to consistently use mac instead of hwaddr/mac + * \#468 - code related to adding/editing/deleting links cleaned up + * \#469 - usages of per all changed to loss to be consistent + * \#470 - variables with numbered names now use numbers directly + * \#471 - node startup is no longer embedded within its constructor + * \#472 - code updated to refer to interfaces consistently as iface + * \#475 - code updates changing how ip addresses are stored on interfaces + * \#476 - executables to check for moved into own module core.executables + * \#486 - core will now install into its own python virtual environment managed by poetry +* core-daemon + * updates to properly save/load distributed servers to xml + * \#474 - added type hinting to all service files + * \#478 - fixed typo in config service directory + * \#479 - opening an xml file will now cycle through states like a normal session + * \#480 - ovs configuration will now save/load from xml and display in guis + * \#484 - changes to support adding emane links during runtime +* core-pygui + * fixed issue not displaying services for the default group in service dialogs + * fixed issue starting a session when the daemon is not present + * fixed issue attempting to open terminals for invalid nodes + * fixed issue syncing session location + * fixed issue joining a session with mobility, not in runtime + * added cpu usage monitor to status bar + * emane configurations can now be seen during runtime + * rj45 nodes can only have one link + * disabling throughputs will clear labels + * improvements to custom service copy + * link options will now be drawn on as a label + * updates to handle runtime link events + * \#477 - added optional details pane for a quick view of node/link details + * \#485 - pygui fixed observer widget for invalid nodes + * \#496 - improved alert handling +* core-gui + * \#493 - increased frame size to show all emane configuration options +* gRPC API + * added set session user rpc + * added cpu usage stream + * interface objects returned from get_node will now provide node_id, net_id, and net2_id data + * peer to peer nodes will not be included in get_session calls + * pathloss events will now throw an error when nem id not found + * \#481 - link rpc calls will broadcast out + * \#496 - added alert rpc call +* Services + * fixed issue reading files in security services + * \#494 - add staticd to daemons list for frr services + +## 2020-06-11 CORE 6.5.0 +* Breaking Changes + * CoreNode.newnetif - both parameters are required and now takes an InterfaceData object as its second parameter + * CoreNetworkBase.linkconfig - now takes a LinkOptions parameter instead of a subset of some of the options (ie bandwidth, delay, etc) + * \#453 - Session.add_node and Session.get_node now requires the node class you expect to create/retrieve + * \#458 - rj45 cleanup to only inherit from one class +* Enhancements + * fixed issues with handling bad commands for TLV execute messages + * removed unused boot.sh from CoreNode types + * added linkconfig to CoreNetworkBase and cleaned up function signature + * emane position hook now saves geo position to node + * emane pathloss support + * core.emulator.emudata leveraged dataclass and type hinting + * \#459 - updated transport type usage to an enum + * \#460 - updated network policy type usage to an enum +* Python GUI Enhancements + * fixed throughput events do not work for joined sessions + * fixed exiting app with a toolbar picker showing + * fixed issue with creating interfaces and reusing subnets after deletion + * fixed issue with moving text shapes + * fixed scaling with custom node selected + * fixed toolbar state switching issues + * enable/disable toolbar when running stop/start + * marker config integrated into toolbar + * improved color picker layout + * shapes can now be moved while drawing shapes + * added observers to toolbar in run mode +* gRPC API + * node events will now have geo positional data + * node geo data is now returned in get_session and get_node calls + * \#451 - added wlan link api to allow direct linking/unlinking of wireless links between nodes + * \#462 - added streaming call for sending node position/geo changes + * \#463 - added streaming call for emane pathloss events +* Bugfixes + * \#454 - fixed issue creating docker nodes, but containers are now required to have networking tools + * \#466 - fixed issue in python gui when xml file is loading nodes with no ip4 addresses + +## 2020-05-11 CORE 6.4.0 +* Enhancements + * updates to core-route-monitor, allow specific session, configurable settings, and properly + listen on all interfaces + * install.sh now has a "-r" option to help with reinstalling from current branch and installing + current python dependencies + * \#202 - enable OSPFv2 fast convergence + * \#178 - added comments to OVS service +* Python GUI Enhancements + * added initial documentation to help support usage + * supports drawing multiple links for wireless connections + * supports differentiating wireless networks with different colored links + * implemented unlink in node context menu to delete links to other nodes + * implemented node run tool dialog + * implemented find node dialog + * implemented address configuration dialog + * implemented mac configuration dialog + * updated link address creation to more closely mimic prior behavior + * updated configuration to use yaml class based configs + * implemented auto grid layout for nodes + * fixed drawn wlan ranges during configuration +* Bugfixes + * no longer writes link option data for WLAN/EMANE links in XML + * avoid configuring links for WLAN/EMANE link options in XML, due to them being written to XML prior + * updates to allow building python docs again + * \#431 - peer to peer node uplink link data was not using an enum properly due to code changes + * \#432 - loading XML was not setting EMANE nodes model + * \#435 - loading XML was not maintaining existing session options + * \#448 - fixed issue sorting hooks being saved to XML + +## 2020-04-13 CORE 6.3.0 +* Features + * \#424 - added FRR IS-IS service +* Enhancements + * \#414 - update GUI OSPFv2 adjacency widget to work with FRR + * \#416 - EMANE links can now be drawn for 80211 and RF Pipe models + * \#418 #409 - code cleanup + * \#425 - added route monitor script for SDT3D integration + * a formal error will now be thrown when EMANE binding are not installed, but attempted to be used + * node positions will now default to 0,0 to avoid GUI errors, when one is not provided + * improved SDT3D integration, multiple link support and usage of custom layers +* Python GUI Enhancements + * enabled edit menu delete + * cleaned up node context menu and enabled delete +* Bugfixes + * \#427 - fixed issue in default route service + * \#426 - fixed issue reading ipsec template file + * \#420 - fixed issue with TLV API udp handler + * \#411 - allow wlan to be configured with 0 values + * \#415 - general EMANE configuration was not being saved/loaded from XML + +## 2020-03-16 CORE 6.2.0 +* gRPC API + * Added call to execute python script +* Enhancements + * \#371 - improved coretk gui scaling + * \#374 - display range visually for wlan in coretk gui, when configuring + * \#377 - improved coretk error dialogs + * \#379 - fixed issues with core converting between x,y and lon,lat for values that would cross utm zones + * \#384 - sdt integration moved internally to core code allowing it to work for coretk gui as well + * \#387 - coretk gui will now auto detect potential valid terminal and command to use for interacting with nodes during runtime + * \#389 - coretk gui will now attempt to reconnect to daemon without need to restart + * \#395 - coretk gui now has "save" and "save as" menu options + * \#402 - coretk will now allow terminal preference to be directly edited +* Bugfixes + * \#375 - fixed issues with emane event monitor handling data + * \#381 - executing a python script will now wait until completion before looking to join a new session + * \#391 - fixed configuring node ip addresses in coretk gui + * \#392 - fixed coretk link display when addresses are cleared out + * \#393 - coretk gui will properly clear marker annotations when switching sessions + * \#396 - Docker and LXC nodes will now properly save to XML + * \#406- WLAN bridge initialization was not ran when all nodes are disconnected + +## 2020-02-20 CORE 6.1.0 +* New + * config services - these services leverage a proper template engine and have configurable parameters, given enough time may replace existing services + * core-imn-to-xml - IMN to XML utility script + * replaced internal code for determining ip/mac address with netaddr library +* Enhancements + * added distributed package for built packages + * made use of python type hinting for functions and their return values + * updated Quagga zebra service to remove deprecated warning +* Removed + * removed stale ns3 code +* CORETK GUI + * added logging + * improved error dialog + * properly use global ipv6 addresses for nodes + * disable proxy usage by default, flag available to enable +* gRPC API + * add_link - now returns created interface information + * set_node_service - can now set files and directories to properly replicate previous usage + * get_emane_event_channel - return information related to the currently used emane event channel +* Bugfixes + * fixed session SDT functionality back to working order, due to python3 changes + * avoid shutting down services for nodes that are not up + * EMANE bypass model options will now display properly in GUIs + * XML scenarios will now properly read in custom node icons + * \#372 - fixed mobility waypoint comparisons + * \#370 - fixed radvd service + * \#368 - updated frr services to properly start staticd when needed + * \#358 - fixed systemd service install path + * \#350 - fixed frr babel wireless configuration + * \#354 - updated frr to reset interfaces to properly take configurations + +## 2020-01-01 CORE 6.0.0 +* New + * beta release of the python based tk GUI, use **coretk-gui** to try it out, plan will be to eventually sunset the old GUI once this is good enough + * this GUI will allow us to provide enhancements and a consistent python dev environment for developers +* Major Changes + * python3.6+ support only, due to python2 EOL https://pyfound.blogspot.com/2019/12/python-2-sunset.html + * distributed sessions now leverages the fabric library for sending remote SSH commands +* Enhancements + * changed usage of bridge-utils to using ip based bridge commands due to deprecation + * installation.sh script to help automate a standard make install or dev install + * when sessions are created without an id they will now always start from 1 and return the next unused id + * gRPC is now running by default +* Session API + * removed **create_emane_network** and **create_wlan_network** to help force using **add_node** for all cases + * removed **session.master** as it was only used for previous distributed sessions + * updated **add_node** to allow providing a custom class for node creation +* gRPC API + * added get all services configurations + * added get all wlan configurations + * added start/stop session calls, provides more freedom for startup and shutdown logic + * session events now have a session id to help differentiate which session they are coming from + * throughput events now require a session id and responses include session id for differentiating data + * session events can now be subscribed to with a subset of events or all + * emane model config data now include interface ids properly + * sessions returned from get sessions call may include file names when created from xml + * when opening an xml the session can now be started or not + * edit node will now broadcast the edit for others to listen to + * all config responses will now be in the form of a mapped value of key to ConfigOption, or a list of these when retrieving all, sometimes the config response may be wrapped in a different message to include other metadata +* Bugfixes + * \#311 - initialize ebtables chains for wlan networks only + * \#312 - removed sudo from init script + * \#313 - check if interface exists before flushing, previously would log an exception that didn't matter + * \#314 - node locations stored as floats instead of ints to avoid mobility calculations due to loss of precision + * \#321 - python installation path will be based on distr ibution/python building it + * emane options xml parsing didn't properly take into account the **emane_prefix** configuration + * updates services that checked for ipv4/ipv6 addresses to not fail for valid ipv6 addresses with a decimal +* Documentation + * updated NRL links to new GitHub locations + * updates for distributed session + * updates to dev guide + * updates to examples LXD/Docker setup + * updates to FRR service documentation + * gRPC get node service file will not throw an exception when node doesn't exist + +## 2019-10-12 CORE 5.5.2 +* gRPC + * Added emane_link API for linking/unlinking EMANE nodes within the GUI +* Bugfixes + * Fixed python3 issues when configuring WLAN nodes + * Fixed issue due to refactoring when running distributed + * Fixed issue when running python script from GUI + +## 2019-10-09 CORE 5.5.1 +* Bugfix + * Fixed issue with 5.5.0 refactoring causing issues in python2. + * Fixed python3 issues with NRL services + +## 2019-10-03 CORE 5.5.0 +* Documentation + * updated dependencies for building OSPF MDR on installation page + * added python/pip instruction on installation page + * added ethtool dependency for CORE +* GUI + * removed experimental OVS node to avoid confusion and issues related to using it +* Daemon + * fixed core-daemon --ovs flag back to working order for running CORE using OVS bridges instead of Linux bridges + * updated requirements.txt to refer to configparser 4.0.2, due to 4.0.1 removal by developers + * update to fail fast for dependent executables that are not found within PATH + * update to not load services that fail during service.on_load and move on +* Build + * fixed issue with configure script when using option flags + * python install path will use the native install path for AM_PATH_PYTHON, instead of coercing to python3 +* Issues + * \#271 - OVS node error in GUI + * \#291 - configparser 4.0.1 issue + * \#290 - python3 path issue when building + +## 2019-09-23 CORE 5.4.0 +* Documentation + * Updates to documentation dev guide +* Improvements + * Added support for Pipenv for development + * Added configuration to leverage pre-commit during development + * Added configuration to leverage isort, black, and flake8 during development + * Added Github Actions to help verify pull requests in the same way as pre-commit +* Issues + * \#279 - WLAN configuration does not get set by default + * \#272 - error installing python package futures==3.2.0 +* Pull Requests + * \#275 - Disable MAC learning on WLAN + * \#281 - Bumped jackson version on corefx + +## 2019-07-05 CORE 5.3.1 +* Documentation + * Updates to provide more information regarding several of the included services +* Issues + * \#252 - fixed changing wlan configurations during runtime + * \#256 - fixed mobility waypoint comparison for python3 + * \#174 - turn tx/rx checksums off by default as they will never be valid for virtual interfaces + * \#259 - fixes for distributed EMANE + * \#260 - fixed issue with how execfile was being used due to it not existing within python3 + +## 2019-06-10 CORE 5.3.0 +* Enhancements + * python 2 / 3 support + * added new API using [gRPC](https://grpc.io/) + * --grpc --grpc-port --grpc-address flags added to core-daemon + * core.api.grpc.client.CoreGrpcClient, provides a convenience wrapper for leveraging the API +* Docs + * Updates to installation instructions for latest changes +* Services + * Added FRR service +* EMANE + * Added EMANE prefix configuration when looking for emane model manifest files + * requires configuring **emane_prefix** in /etc/core/core.conf +* Cleanup + * Refactoring of the core python package structure, trying to help provide better organization and + logical groupings +* Issues + * \#246 - Fixed network to network link handling when reading xml files + * \#236 - Fixed storing/reading of link configuration values within xml files + * \#170 - FRR Service + * \#155 - EMANE path configuration + * \#233 - Python 3 support + * \#245 - Fixed bidirectional link configurations when reading from xml files + * \#208 - gRPC API + * Fixed link configuration dup handling when loaded from xml files + +## 2019-06-07 CORE 5.2.2 +* Enhancements: + * adds back in core-daemon udp support for coresendmsg, people may have depended on previously for certain scenarios +* Bug Fixes: + * fixes issue in GUI that would prevent moving nodes during mobility scenarios + +## 2019-03-25 CORE 5.2.1 +* Packaging: + * documentation no longer builds by default, must use configure flag + * added configure flag to allow only building vcmd + * sphinx will no long be required when not building documentation +* Services: + * Added source NAT service + * Fixed DHCP service for Ubuntu 18.04 +* BUGFIXES: + * \#188 - properly remove session on delete TLV API call + * \#192 - updated default gnome terminal command for nodes to be Ubuntu 18.04 compatible + * \#193 - updates to service validation, will retry on failure and better exception logging + * \#195 - TLV link message data fix + * \#196 - fix to avoid clearing out default services + * \#197 - removed wireless_link_all API from EmuSession + * \#216 - updated default WLAN bandwidth to 54Mbps + * \#223 - fix to saving RJ45 to session XML files + +## 2018-05-22 CORE 5.1 +* DAEMON: + * removed and cleared out code that is either legacy or no longer supported (Xen, BSD, Kernel patching, RPM/DEB + specific files) + * default nodes are now set in the node map + * moved ns3 and netns directories to the top of the repo + * changes to make use of fpm as the tool for building packages + * removed usage of logzero to avoid dependency issues for built packages + * removed daemon addons directory + * added CoreEmu to core.emulator.coreemu to help begin serving as the basis for a more formal API for scripting + and creating new external APIs out of + * cleaned up logging, moved more logging to DEBUG from INFO, tried to mold INFO message to be more simple and + informative + * EMANE 1.0.1-1.21 supported + * updates to leverage EMANE python bindings for dynamically parsing phy/mac manifest files + * example custom EMANE model lives under /usr/share/core/examples/myemane/examplemodel.py + * EMANE TDMA model now supports an option to start a TDMA schedule when running + * fixed issues with coresendmsg script due to code refactoring + * added make target for generating documentation "make doc" + * Python 2.7+ is now required + * ns3 is no longer bundled by default, but will be produced as a separate package for installation +* GUI: + * updated broken help links in GUI Help->About +* Packaging: + * fixed PYTHON_PATH to PYTHONPATH in sysv script + * added make command to leverage FPM as the tool for creating deb/rpm packages going forward, there is documentation + within README.md to try it out +* TEST: + * fixed some broken tests + * new test cases based on CoreEmu usage +* BUGFIXES: + * \#142 - duplication of custom services + * \#136 - sphinx-apidoc command not found + * \#137 - make command fails when using distclean + +## 2017-09-01 CORE 5.0 +* DEVELOPMENT: + * support for editorconfig to help standardize development across IDEs, from the defined configuration file + * support for sonarqube analysis, from the defined configuration file +* DAEMON: + * code cleanup and improvements to adhere to coding standards (SonarQube) + * leverage "logzero" module to make easy usage of the standard logging module + * improvements to documentation across the code base + * initial work to separate the dependence on TCP API messaging from the core library (easier core scripting) + * beta support for running core in Open vSwitch mode, leveraging Open vSwitch bridges, instead of Linux bridges +* SERVICES: + * added Ryu SDN controller service + * added Open vSwitch service +* TEST: + * added unit/integration tests to support validating changes going forward +* BUGFIXES: + * merged pull requests for: #115, #110, #109, #107, #106, #105, #103, #102, #101, #96 + +## 2015-06-05 CORE 4.8 +* EMANE: + * support for EMANE 0.9.2 + * run emane in each container when using EMANE 0.9.2 + * support using separate control networks for EMANE OTA and event traffic +* GUI: + * fixed an issue where the adjacency widget lines pointed to old node positions + * fixed an issue where not all EMANE 0.9.x IEEE 802.11 MAC parameter were configurable + * fixed an issue related to running python scripts from the GUI when using tcl/tk version 8.6 + * improved batch mode execution to display the check emulation light status + * improved managing multiple sessions + * improved support for using multiple canvases + * added a reload option to the file menu to revert back to a saved scenario +* DAEMON: + * support exporting scenarios in NRL Network Modeling Framework 1.0 XML format + * support importing scenarios in NRL Network Modeling Framework 1.0 XML format + * support exporting the deployed scenario state in NRL NMF XML 1.0 format + * improved EMANE post-startup processing to better synchronize distributed emulations + * improved how addresses are assigned to tun/tap devices + * added support for python state-change callbacks +* SERVICES: + * added mgen sink and mgen actor services + * added oslrv2 and olsr.org services + * added a docker service +* BUILD: + * improved the install/uninstall process + * improved debian and rpm packaging +* BUGFIXES: + * updated the http service for ubuntu 14.04 + * improved included examples + * shortened the length of network interface names + * improved how the core system service manages running the core daemon + * fixed an issues related to applying session configuration setting + * improved detecting when a distributed emulation is already running + * improved documentation + +## 2014-08-06 CORE 4.7 +* EMANE: + * support for EMANE 0.9.1 + * fix error when using Comm Effect model with loss/duplicate string values + * enable flow control in virtual transport if enabled in the MAC model + * fix bug #150 where EMANE event service/address port were not used +* GUI: + * support Tcl/Tk 8.6 when available + * added --(a)ddress and --(p)ort arguments to core-gui command-line + * added File > Execute XML or Python script... option + * added File > Execute Python script with options... menu item + * when executing Python script from GUI, run in background thread, wait for + RUNTIME state + * enter RUNTIME state when start button pressed with empty canvas + * added support for asymmetric link effects + * support link delays up to 274 seconds (netem maximum) + * allow runtime changes of WLAN link effects +* DAEMON: + * set NODE_NAME, NODE_NUMBER, SESSION_SHORT in default vnoded environment + * changed host device naming to use veth, tap prefixes; b.n.SS for bridges + * allow parsing XML files into live running session + * enable link effects between hub/switch and hub/switch connections + * update MDR service to use broadcast interfaces for non-WLAN links + * allow node class to be specified when initializing XML parser + * save and parse canvas origin (reference point) and scale in MP XML + * up/down control script session option + * fix hash calculation used to determine GRE tunnel keys + * use shell script to detach SMF on startup + * added NRL services for mgen sink and nrlolsrv2 + * use SDT URL session option + * added core-manage tool for addons to add/remove/check services, models, + and custom node types +* API: + * implement local flag in Execute Message for running host commands + * jitter changed to 64-bit value to align with delay in Link Message + * added unidirectional link flag TLV to Link Message + * added reconfigure event type for re-generating service config files + * return errors in API with failed services +* BUGFIXES: + * fix HTTP service running under Ubuntu + * fixed the following bugs: #150, 169, 188, 220, 225, 230, 231, 242, 244, + 247, 248, 250, 251 + +## 2013-09-25 CORE 4.6 +* NOTE: cored is now core-daemon, and core is now core-gui (for Debian acceptance) +* NOTE: /etc/init.d/core is now /etc/init.d/core-daemon (for insserv compatibility) +* EMANE: + * don't start EMANE locally if no local NEMs + * EMANE poststartup() to re-transmit location events during initialization + * added debug port to EMANE options + * added a basic EMANE 802.11 CORE Python script example + * expose transport XML block generation to EmaneModels + * expose NEM entry to the EmaneModel so it can be overridden by a model + * add the control interface bridge prior to starting EMANE, as some models may + * depend on the controlnet functionality + * added EMANE model to CORE converter + * parse lat/long/alt from node messages, for moving nodes using command-line + * fix bug #196 incorrect distance when traversing UTM zones +* GUI: + * added Cut, Copy, and Paste options to the Edit menu + * paste will copy selected services and take care of node and interface + * renumbering + * implement Edit > Find dialog for searching nodes and links + * when copying existing file for a service, perform string replacement of: + * "~", "%SESSION%", "%SESSION_DIR%", "%SESSION_USER%", "%NODE%", "%NODENAME%" + * use CORE_DATA_DIR insteadof LIBDIR + * fix Adjacency Widget to work with OSPFv2 only networks +* BUILD: + * build/packaging improvements for inclusion on Debian + * fix error when running scenario with a mobility script in batch mode + * include Linux kernel patches for 3.8 + * renamed core-cleanup.sh to core-cleanup for Debian conformance + * don't always generate man pages from Makefile; new manpages for + coresendmsg and core-daemon +* BUGFIXES: + * don't auto-assign IPv4/IPv6 addresses when none received in Link Messages (session reconnect) + * fixed lock view + * fix GUI spinbox errors for Tk 8.5.8 (RHEL/CentOS 6.2) + * fix broker node count for distributed session entering the RUNTIME state when + * (non-EMANE) WLANs or GreTapBridges are involved; + * fix "file exists" error message when distributed session number is re-used + * and servers file is written + * fix bug #194 configuration dialog too long, make dialog scrollable/resizable + * allow float values for loss and duplicates percent + * fix the following bugs: 166, 172, 177, 178, 192, 194, 196, 201, 202, + 205, 206, 210, 212, 213, 214, 221 + +## 2013-04-13 CORE 4.5 +* GUI: + * improved behavior when starting GUI without daemon, or using File New after connection with daemon is lost + * fix various GUI issues when reconnecting to a session + * support 3D GUI via output to SDT3D + * added "Execute Python script..." entry to the File Menu + * support user-defined terminal program instead of hard-coded xterm + * added session options for "enable RJ45s", "preserve session dir" + * added buttons to the IP Addresses dialog for removing all/selected IPv4/IPv6 + * allow sessions with multiple canvases to enter RUNTIME state + * added "--addons" startup mode to pass control to code included from addons dir + * added "Locked" entry to View menu to prevent moving items + * use currently selected node type when invoking a topology generator + * updated throughput plots with resizing, color picker, plot labels, locked scales, and save/load plot + configuration with imn file + * improved session dialog +* EMANE: + * EMANE 0.8.1 support with backwards-compatibility for 0.7.4 + * extend CommEffect model to generate CommEffect events upon receipt of Link Messages having link effects +* Services: + * updated FTP service with root directory for anonymous users + * added HTTP, PCAP, BIRD, RADVD, and Babel services + * support copying existing files instead of always generating them + * added "Services..." entry to node right-click menu + * added "View" button for side-by-side comparison when copying customized config files + * updated Quagga daemons to wait for zebra.vty VTY file before starting +* General: + * XML import and export + * renamed "cored.py" to "cored", "coresendmsg.py" to "coresendmsg" + * code reorganization and clean-up + * updated XML export to write NetworkPlan, MotionPlan, and ServicePlan within a Scenario tag, added new + "Save As XML..." File menu entry + * added script_start/pause/stop options to Ns2ScriptedMobility + * "python" source sub-directory renamed to "daemon" + * added "cored -e" option to execute a Python script, adding its session to the active sessions list, allowing for + GUI connection + * support comma-separated list for custom_services_dir in core.conf file + * updated kernel patches for Linux kernel 3.5 + * support RFC 6164-style IPv6 /127 addressing +* ns-3: + * integrate ns-3 node location between CORE and ns-3 simulation + * added ns-3 random walk mobility example + * updated ns-3 Wifi example to allow GUI connection and moving of nodes +* fixed the following bugs: 54, 103, 111, 136, 145, 153, 157, 160, 161, 162, 164, 165, 168, 170, 171, 173, 174, 176, +184, 190, 193 + +## 2012-09-25 CORE 4.4 +* GUI: + * real-time bandwidth plotting tool + * added Wireshark and tshark right-click menu items + * X,Y coordinates shown in the status bar + * updated GUI attribute option to link messages for changing color/width/dash + * added sample IPsec and VPN scenarios, how many nodes script + * added jitter parameter to WLANs + * renamed Experiment menu to Session menu, added session options + * use 'key=value' configuration for services, EMANE models, WLAN models, etc. + * save only service values that have been customized + * copy service parameters from one customized service to another + * right-click menu to start/stop/restart each service +* EMANE: + * EMANE 0.7.4 support + * added support for EMANE CommEffect model and Comm Effect controller GUI + * added support for EMANE Raw Transport when using RJ45 devices +* Services: + * improved service customization; allow a service to define custom Tcl tab + * added vtysh.conf for Quagga service to support 'write mem' + * support scheduled events and services that start N seconds after runtime + * added UCARP service +* Documentation: + * converted the CORE manual to reStructuredText using Sphinx; added Python docs +* General: + * Python code reorganization + * improved cored.py thread locking + * merged xen branch into trunk + * added an event queue to a session with notion of time zero + * added UDP support to cored.py + * use UDP by default in coresendmsg.py; added '-H' option to print examples + * enter a bash shell by default when running vcmd with no arguments + * fixes to distributed emulation entering runtime state + * write 'nodes' file upon session startup + * make session number and other attributes available in environment + * support /etc/core/environment and ~/.core/environment files + * added Ns2ScriptedMobility model to Python, removed from the GUI + * namespace nodes mount a private /sys + * fixed the following bugs: 80, 81, 84, 99, 104, 109, 110, 122, 124, 131, 133, 134, 135, 137, 140, 143, 144, 146, + 147, 151, 154, 155 + +## 2012-03-07 CORE 4.3 +* EMANE 0.7.2 and 0.7.3 support +* hook scripts: customize actions at any of six different session states +* Check Emulation Light (CEL) exception feedback system +* added FTP and XORP services, and service validate commands +* services can flag when customization is required +* Python classes to support ns-3 simulation experiments +* write state, node X,Y position, and servers to pycore session dir +* removed over 9,000 lines of unused GUI code +* performance monitoring script +* batch mode improvements and --closebatch option +* export session to EmulationScript XML files +* basic range model moved from GUI to Python, supports 3D coordinates +* improved WLAN dialog with tabs +* added PhysicalNode class for joining real nodes with emulated networks +* fixed the following bugs: 50, 75, 76, 79, 82, 83, 85, 86, 89, 90, 92, 94, 96, 98, 100, 112, 113, 116, 119, 120 + +## 2011-08-19 CORE 4.2 +* EMANE 0.7.1 support + * support for Bypass model, Universal PHY, logging, realtime +* configurable MAC addresses +* control interfaces (backchannel between node and host) +* service customization dialog improved (tabbed) +* new testing scripts for MDR and EMANE performance testing +* improved upgrading of old imn files +* new coresendmsg.py utility (deprecates libcoreapi and coreapisend) +* new security services, custom service becomes UserDefined +* new services and Python scripting chapters in manual +* fixes to distributed emulation, linking tunnels/RJ45s with WLANs/hubs/switches +* fixed the following bugs: 18, 32, 34, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 55, 57, 58, 60, 62, 64, +65, 66, 68, 71, 72, 74 + +## 2011-01-05 CORE 4.1 +* new icons for toolbars and nodes +* node services introduced, node models deprecated +* customizable node types +* traffic flow editor with MGEN support +* user configs moved from /etc/core/`*` to ~/.core/ +* allocate addresses from custom IPv4/IPv6 prefixes +* distributed emulation using GRE tunnels +* FreeBSD 8.1 now uses cored.py +* EMANE 0.6.4 support +* numerous bugfixes + +## 2010-08-17 CORE 4.0 +* Python framework with Linux network namespace (netns) support (Linux netns is now the primary supported platform) +* ability to close the GUI and later reconnect to a running session (netns only) +* EMANE integration (netns only) +* new topology generators, host file generator +* user-editable Observer Widgets +* use of /etc/core instead of /usr/local/etc/core +* various bugfixes + +## 2009-09-15 CORE 3.5 + +## 2009-06-23 CORE 3.4 + +## 2009-03-11 CORE 3.3 diff --git a/Changelog b/Changelog deleted file mode 100644 index dd034ab6..00000000 --- a/Changelog +++ /dev/null @@ -1,324 +0,0 @@ -2018-05-22 CORE 5.1 - * DAEMON: - - removed and cleared out code that is either legacy or no longer supported (Xen, BSD, Kernel patching, RPM/DEB specific files) - - default nodes are now set in the node map - - moved ns3 and netns directories to the top of the repo - - changes to make use of fpm as the tool for building packages - - removed usage of logzero to avoid dependency issues for built packages - - removed daemon addons directory - - added CoreEmu to core.emulator.coreemu to help begin serving as the basis for a more formal API for scripting and creating new external APIs out of - - cleaned up logging, moved more logging to DEBUG from INFO, tried to mold INFO message to be more simple and informative - - EMANE 1.0.1-1.21 supported - - updates to leverage EMANE python bindings for dynamically parsing phy/mac manifest files - - example custom EMANE model lives under /usr/share/core/examples/myemane/examplemodel.py - - EMANE TDMA model now supports an option to start a TDMA schedule when running - - fixed issues with coresendmsg script due to code refactoring - - added make target for generating documentation "make doc" - - Python 2.7+ is now required - - ns3 is no longer bundled by default, but will be produced as a separate package for installation - * GUI - - updated broken help links in GUI Help->About - * Packaging - - fixed PYTHON_PATH to PYTHONPATH in sysv script - - added make command to leverage FPM as the tool for creating deb/rpm packages going forward, there is documentation within README.md to try it out - * TEST: - - fixed some broken tests - - new test cases based on CoreEmu usage - * BUGFIXES: - - #142 - duplication of custom services - - #136 - sphinx-apidoc command not found - - #137 - make command fails when using distclean - -2017-09-01 CORE 5.0 - * DEVELOPMENT: - - support for editorconfig to help standardize development across IDEs, from the defined configuration file - - support for sonarqube analysis, from the defined configuration file - * DAEMON: - - code cleanup and improvements to adhere to coding standards (SonarQube) - - leverage "logzero" module to make easy usage of the standard logging module - - improvements to documentation across the code base - - initial work to separate the dependence on TCP API messaging from the core library (easier core scripting) - - beta support for running core in Open vSwitch mode, leveraging Open vSwitch bridges, instead of Linux bridges - * SERVICES: - - added Ryu SDN controller service - - added Open vSwitch service - * TEST: - - added unit/integration tests to support validating changes going forward - * BUGFIXES: - - merged pull requests for: #115, #110, #109, #107, #106, #105, #103, #102, #101, #96 - -2015-06-05 CORE 4.8 - * EMANE: - - support for EMANE 0.9.2 - - run emane in each container when using EMANE 0.9.2 - - support using separate control networks for EMANE OTA and event traffic - * GUI: - - fixed an issue where the adjacency widget lines pointed to old node positions - - fixed an issue where not all EMANE 0.9.x IEEE 802.11 MAC parameter were configurable - - fixed an issue related to running python scripts from the GUI when using tcl/tk version 8.6 - - improved batch mode execution to display the check emulation light status - - improved managing multiple sessions - - improved support for using multiple canvases - - added a reload option to the file menu to revert back to a saved scenario - * DAEMON: - - support exporting scenarios in NRL Network Modeling Framework 1.0 XML format - - support importing scenarios in NRL Network Modeling Framework 1.0 XML format - - support exporting the deployed scenario state in NRL NMF XML 1.0 format - - improved EMANE post-startup processing to better synchronize distributed emulations - - improved how addresses are assigned to tun/tap devices - - added support for python state-change callbacks - * SERVICES: - - added mgen sink and mgen actor services - - added oslrv2 and olsr.org services - - added a docker service - * BUILD: - - improved the install/uninstall process - - improved debian and rpm packaging - * BUGFIXES: - - updated the http service for ubuntu 14.04 - - improved included examples - - shortened the length of network interface names - - improved how the core system service manages running the core daemon - - fixed an issues related to applying session configuration setting - - improved detecting when a distributed emulation is already running - - improved documentation - -2014-08-06 CORE 4.7 - - * EMANE: - - support for EMANE 0.9.1 - - fix error when using Comm Effect model with loss/duplicate string values - - enable flow control in virtual transport if enabled in the MAC model - - fix bug #150 where EMANE event service/address port were not used - * GUI: - - support Tcl/Tk 8.6 when available - - added --(a)ddress and --(p)ort arguments to core-gui command-line - - added File > Execute XML or Python script... option - - added File > Execute Python script with options... menu item - - when executing Python script from GUI, run in background thread, wait for - RUNTIME state - - enter RUNTIME state when start button pressed with empty canvas - - added support for asymmetric link effects - - support link delays up to 274 seconds (netem maximum) - - allow runtime changes of WLAN link effects - * DAEMON: - - set NODE_NAME, NODE_NUMBER, SESSION_SHORT in default vnoded environment - - changed host device naming to use veth, tap prefixes; b.n.SS for bridges - - allow parsing XML files into live running session - - enable link effects between hub/switch and hub/switch connections - - update MDR service to use broadcast interfaces for non-WLAN links - - allow node class to be specified when initializing XML parser - - save and parse canvas origin (reference point) and scale in MP XML - - up/down control script session option - - fix hash calculation used to determine GRE tunnel keys - - use shell script to detach SMF on startup - - added NRL services for mgen sink and nrlolsrv2 - - use SDT URL session option - - added core-manage tool for addons to add/remove/check services, models, - and custom node types - * API: - - implement local flag in Execute Message for running host commands - - jitter changed to 64-bit value to align with delay in Link Message - - added unidirectional link flag TLV to Link Message - - added reconfigure event type for re-generating service config files - - return errors in API with failed services - * BUGFIXES: - - fix HTTP service running under Ubuntu - - fixed the following bugs: #150, 169, 188, 220, 225, 230, 231, 242, 244, - 247, 248, 250, 251 - -2013-09-25 CORE 4.6 - - * NOTE: cored is now core-daemon, and core is now core-gui (for Debian - acceptance) - * NOTE: /etc/init.d/core is now /etc/init.d/core-daemon (for insserv - compatibility) - * EMANE: - - don't start EMANE locally if no local NEMs - - EMANE poststartup() to re-transmit location events during initialization - - added debug port to EMANE options - - added a basic EMANE 802.11 CORE Python script example - - expose transport XML block generation to EmaneModels - - expose NEM entry to the EmaneModel so it can be overridden by a model - - add the control interface bridge prior to starting EMANE, as some models may - - depend on the controlnet functionality - - added EMANE model to CORE converter - - parse lat/long/alt from node messages, for moving nodes using command-line - - fix bug #196 incorrect distance when traversing UTM zones - - * GUI: - - added Cut, Copy, and Paste options to the Edit menu - - paste will copy selected services and take care of node and interface - - renumbering - - implement Edit > Find dialog for searching nodes and links - - when copying existing file for a service, perform string replacement of: - - "~", "%SESSION%", "%SESSION_DIR%", "%SESSION_USER%", "%NODE%", "%NODENAME%" - - use CORE_DATA_DIR insteadof LIBDIR - - fix Adjacency Widget to work with OSPFv2 only networks - - * BUILD: - - build/packaging improvements for inclusion on Debian - - fix error when running scenario with a mobility script in batch mode - - include Linux kernel patches for 3.8 - - renamed core-cleanup.sh to core-cleanup for Debian conformance - - don't always generate man pages from Makefile; new manpages for - coresendmsg and core-daemon - - * BUGFIXES: - - don't auto-assign IPv4/IPv6 addresses when none received in Link Messages (session reconnect) - - fixed lock view - - fix GUI spinbox errors for Tk 8.5.8 (RHEL/CentOS 6.2) - - fix broker node count for distributed session entering the RUNTIME state when - - (non-EMANE) WLANs or GreTapBridges are involved; - - fix "file exists" error message when distributed session number is re-used - - and servers file is written - - fix bug #194 configuration dialog too long, make dialog scrollable/resizable - - allow float values for loss and duplicates percent - - fix the following bugs: 166, 172, 177, 178, 192, 194, 196, 201, 202, - 205, 206, 210, 212, 213, 214, 221 - -2013-04-13 CORE 4.5 - - * GUI: - - improved behavior when starting GUI without daemon, or using File New after connection with daemon is lost - - fix various GUI issues when reconnecting to a session - - support 3D GUI via output to SDT3D - - added "Execute Python script..." entry to the File Menu - - support user-defined terminal program instead of hard-coded xterm - - added session options for "enable RJ45s", "preserve session dir" - - added buttons to the IP Addresses dialog for removing all/selected IPv4/IPv6 - - allow sessions with multiple canvases to enter RUNTIME state - - added "--addons" startup mode to pass control to code included from addons dir - - added "Locked" entry to View menu to prevent moving items - - use currently selected node type when invoking a topology generator - - updated throughput plots with resizing, color picker, plot labels, locked scales, and save/load plot configuration with imn file - - improved session dialog - * EMANE: - - EMANE 0.8.1 support with backwards-compatibility for 0.7.4 - - extend CommEffect model to generate CommEffect events upon receipt of Link Messages having link effects - * Services: - - updated FTP service with root directory for anonymous users - - added HTTP, PCAP, BIRD, RADVD, and Babel services - - support copying existing files instead of always generating them - - added "Services..." entry to node right-click menu - - added "View" button for side-by-side comparison when copying customized config files - - updated Quagga daemons to wait for zebra.vty VTY file before starting - * General: - - XML import and export - - renamed "cored.py" to "cored", "coresendmsg.py" to "coresendmsg" - - code reorganization and clean-up - - updated XML export to write NetworkPlan, MotionPlan, and ServicePlan within a Scenario tag, added new "Save As XML..." File menu entry - - added script_start/pause/stop options to Ns2ScriptedMobility - - "python" source sub-directory renamed to "daemon" - - added "cored -e" option to execute a Python script, adding its session to the active sessions list, allowing for GUI connection - - support comma-separated list for custom_services_dir in core.conf file - - updated kernel patches for Linux kernel 3.5 - - support RFC 6164-style IPv6 /127 addressing - * ns-3: - - integrate ns-3 node location between CORE and ns-3 simulation - - added ns-3 random walk mobility example - - updated ns-3 Wifi example to allow GUI connection and moving of nodes - * fixed the following bugs: 54, 103, 111, 136, 145, 153, 157, 160, 161, 162, 164, 165, 168, 170, 171, 173, 174, 176, 184, 190, 193 - -2012-09-25 CORE 4.4 - - * GUI: - - real-time bandwidth plotting tool - - added Wireshark and tshark right-click menu items - - X,Y coordinates shown in the status bar - - updated GUI attribute option to link messages for changing color/width/dash - - added sample IPsec and VPN scenarios, how many nodes script - - added jitter parameter to WLANs - - renamed Experiment menu to Session menu, added session options - - use 'key=value' configuration for services, EMANE models, WLAN models, etc. - - save only service values that have been customized - - copy service parameters from one customized service to another - - right-click menu to start/stop/restart each service - * EMANE: - - EMANE 0.7.4 support - - added support for EMANE CommEffect model and Comm Effect controller GUI - - added support for EMANE Raw Transport when using RJ45 devices - * Services: - - improved service customization; allow a service to define custom Tcl tab - - added vtysh.conf for Quagga service to support 'write mem' - - support scheduled events and services that start N seconds after runtime - - added UCARP service - * Documentation: - - converted the CORE manual to reStructuredText using Sphinx; added Python docs - * General: - - Python code reorganization - - improved cored.py thread locking - - merged xen branch into trunk - - added an event queue to a session with notion of time zero - - added UDP support to cored.py - - use UDP by default in coresendmsg.py; added '-H' option to print examples - - enter a bash shell by default when running vcmd with no arguments - - fixes to distributed emulation entering runtime state - - write 'nodes' file upon session startup - - make session number and other attributes available in environment - - support /etc/core/environment and ~/.core/environment files - - added Ns2ScriptedMobility model to Python, removed from the GUI - - namespace nodes mount a private /sys - - - fixed the following bugs: 80, 81, 84, 99, 104, 109, 110, 122, 124, 131, 133, 134, 135, 137, 140, 143, 144, 146, 147, 151, 154, 155 - -2012-03-07 CORE 4.3 - - * EMANE 0.7.2 and 0.7.3 support - * hook scripts: customize actions at any of six different session states - * Check Emulation Light (CEL) exception feedback system - * added FTP and XORP services, and service validate commands - * services can flag when customization is required - * Python classes to support ns-3 simulation experiments - * write state, node X,Y position, and servers to pycore session dir - * removed over 9,000 lines of unused GUI code - * performance monitoring script - * batch mode improvements and --closebatch option - * export session to EmulationScript XML files - * basic range model moved from GUI to Python, supports 3D coordinates - * improved WLAN dialog with tabs - * added PhysicalNode class for joining real nodes with emulated networks - * fixed the following bugs: 50, 75, 76, 79, 82, 83, 85, 86, 89, 90, 92, 94, 96, 98, 100, 112, 113, 116, 119, 120 - -2011-08-19 CORE 4.2 - - * EMANE 0.7.1 support - - support for Bypass model, Universal PHY, logging, realtime - * configurable MAC addresses - * control interfaces (backchannel between node and host) - * service customization dialog improved (tabbed) - * new testing scripts for MDR and EMANE performance testing - * improved upgrading of old imn files - * new coresendmsg.py utility (deprecates libcoreapi and coreapisend) - * new security services, custom service becomes UserDefined - * new services and Python scripting chapters in manual - * fixes to distributed emulation, linking tunnels/RJ45s with WLANs/hubs/switches - * fixed the following bugs: 18, 32, 34, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 55, 57, 58, 60, 62, 64, 65, 66, 68, 71, 72, 74 - -2011-01-05 CORE 4.1 - * new icons for toolbars and nodes - * node services introduced, node models deprecated - * customizable node types - * traffic flow editor with MGEN support - * user configs moved from /etc/core/`*` to ~/.core/ - * allocate addresses from custom IPv4/IPv6 prefixes - * distributed emulation using GRE tunnels - * FreeBSD 8.1 now uses cored.py - * EMANE 0.6.4 support - * numerous bugfixes - -2010-08-17 CORE 4.0 - * Python framework with Linux network namespace (netns) support (Linux netns is now the primary supported platform) - * ability to close the GUI and later reconnect to a running session (netns only) - * EMANE integration (netns only) - * new topology generators, host file generator - * user-editable Observer Widgets - * use of /etc/core instead of /usr/local/etc/core - * various bugfixes - -2009-09-15 CORE 3.5 - -2009-06-23 CORE 3.4 - -2009-03-11 CORE 3.3 - diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..155cacc0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,126 @@ +# syntax=docker/dockerfile:1 +FROM ubuntu:22.04 +LABEL Description="CORE Docker Ubuntu Image" + +ARG PREFIX=/usr/local +ARG BRANCH=master +ARG PROTOC_VERSION=3.19.6 +ARG VENV_PATH=/opt/core/venv +ENV DEBIAN_FRONTEND=noninteractive +ENV PATH="$PATH:${VENV_PATH}/bin" +WORKDIR /opt + +# install system dependencies + +RUN apt-get update -y && \ + apt-get install -y software-properties-common + +RUN add-apt-repository "deb http://archive.ubuntu.com/ubuntu jammy universe" + +RUN apt-get update -y && \ + apt-get install -y --no-install-recommends \ + automake \ + bash \ + ca-certificates \ + ethtool \ + gawk \ + gcc \ + g++ \ + iproute2 \ + iputils-ping \ + libc-dev \ + libev-dev \ + libreadline-dev \ + libtool \ + nftables \ + python3 \ + python3-pip \ + python3-tk \ + pkg-config \ + tk \ + xauth \ + xterm \ + wireshark \ + vim \ + build-essential \ + nano \ + firefox \ + net-tools \ + rsync \ + openssh-server \ + openssh-client \ + vsftpd \ + atftpd \ + atftp \ + mini-httpd \ + lynx \ + tcpdump \ + iperf \ + iperf3 \ + tshark \ + openssh-sftp-server \ + bind9 \ + bind9-utils \ + openvpn \ + isc-dhcp-server \ + isc-dhcp-client \ + whois \ + ipcalc \ + socat \ + hping3 \ + libgtk-3-0 \ + librest-0.7-0 \ + libgtk-3-common \ + dconf-gsettings-backend \ + libsoup-gnome2.4-1 \ + libsoup2.4-1 \ + dconf-service \ + x11-xserver-utils \ + ftp \ + git \ + sudo \ + wget \ + tzdata \ + libpcap-dev \ + libpcre3-dev \ + libprotobuf-dev \ + libxml2-dev \ + protobuf-compiler \ + unzip \ + uuid-dev \ + iproute2 \ + vlc \ + iputils-ping && \ + apt-get autoremove -y + +# install core +RUN git clone https://github.com/coreemu/core && \ + cd core && \ + git checkout ${BRANCH} && \ + ./setup.sh && \ + PATH=/root/.local/bin:$PATH inv install -v -p ${PREFIX} && \ + cd /opt && \ + rm -rf ospf-mdr + +# install emane +RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip && \ + mkdir protoc && \ + unzip protoc-${PROTOC_VERSION}-linux-x86_64.zip -d protoc && \ + git clone https://github.com/adjacentlink/emane.git && \ + cd emane && \ + ./autogen.sh && \ + ./configure --prefix=/usr && \ + make -j$(nproc) && \ + make install && \ + cd src/python && \ + make clean && \ + PATH=/opt/protoc/bin:$PATH make && \ + ${VENV_PATH}/bin/python -m pip install . && \ + cd /opt && \ + rm -rf protoc && \ + rm -rf emane && \ + rm -f protoc-${PROTOC_VERSION}-linux-x86_64.zip + +WORKDIR /root + +CMD /opt/core/venv/bin/core-daemon diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index e70e3dc6..00000000 --- a/Jenkinsfile +++ /dev/null @@ -1,20 +0,0 @@ -pipeline { - agent any - stages { - stage('build core') { - steps { - sh './bootstrap.sh' - sh './configure' - sh 'make' - sh 'sudo make install' - } - } - stage('test core') { - steps { - sh 'pytest daemon/tests/test_core.py' - sh 'pytest daemon/tests/test_gui.py' - sh 'pytest daemon/tests/test_emane.py' - } - } - } -} \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index ee26b643..2b5f29e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,29 +6,26 @@ if WANT_DOCS DOCS = docs man endif -if WANT_GUI - GUI = gui -endif - if WANT_DAEMON - DAEMON = scripts daemon + DAEMON = daemon endif if WANT_NETNS - NETNS = netns ns3 + NETNS = netns endif # keep docs last due to dependencies on binaries -SUBDIRS = $(GUI) $(DAEMON) $(NETNS) $(DOCS) +SUBDIRS = $(DAEMON) $(NETNS) $(DOCS) ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball EXTRA_DIST = bootstrap.sh \ + package \ LICENSE \ README.md \ ASSIGNMENT_OF_COPYRIGHT.pdf \ - Changelog \ + CHANGELOG.md \ .version \ .version.date @@ -44,80 +41,117 @@ DISTCLEANFILES = aclocal.m4 \ MAINTAINERCLEANFILES = .version \ .version.date -define fpm-python = -fpm -s python -t $1 \ - -m "$(PACKAGE_MAINTAINERS)" \ - --vendor "$(PACKAGE_VENDOR)" \ - $2 -endef - -define fpm-gui = -fpm -s dir -t $1 -n core-gui \ +define fpm-distributed-deb = +fpm -s dir -t deb -n core-distributed \ -m "$(PACKAGE_MAINTAINERS)" \ --license "BSD" \ - --description "Common Open Research Emulator GUI front-end" \ - --url http://www.nrl.navy.mil/itd/ncs/products/core \ + --description "Common Open Research Emulator Distributed Package" \ + --url https://github.com/coreemu/core \ --vendor "$(PACKAGE_VENDOR)" \ - -p core-gui_VERSION_ARCH.$1 \ + -p core-distributed_VERSION_ARCH.deb \ -v $(PACKAGE_VERSION) \ - -d "bash" \ - -d "tcl" \ - -d "tk" \ - $2 \ - -C $(DESTDIR) + -d "ethtool" \ + -d "procps" \ + -d "libc6 >= 2.14" \ + -d "bash >= 3.0" \ + -d "nftables" \ + -d "iproute2" \ + -d "libev4" \ + -d "openssh-server" \ + -d "xterm" \ + netns/vnoded=/usr/bin/ \ + netns/vcmd=/usr/bin/ endef -define fpm-daemon-rpm = -fpm -s python -t rpm \ - -p NAME_sysv_VERSION_ARCH.rpm \ - --rpm-init scripts/core-daemon \ - --python-install-bin $(bindir) \ - --python-install-data $(prefix) \ - --python-install-lib $(pythondir) \ +define fpm-distributed-rpm = +fpm -s dir -t rpm -n core-distributed \ -m "$(PACKAGE_MAINTAINERS)" \ + --license "BSD" \ + --description "Common Open Research Emulator Distributed Package" \ + --url https://github.com/coreemu/core \ --vendor "$(PACKAGE_VENDOR)" \ + -p core-distributed_VERSION_ARCH.rpm \ + -v $(PACKAGE_VERSION) \ + -d "ethtool" \ + -d "procps-ng" \ + -d "bash >= 3.0" \ + -d "nftables" \ + -d "iproute" \ + -d "libev" \ + -d "net-tools" \ + -d "openssh-server" \ + -d "xterm" \ + netns/vnoded=/usr/bin/ \ + netns/vcmd=/usr/bin/ +endef + +define fpm-rpm = +fpm -s dir -t rpm -n core \ + -m "$(PACKAGE_MAINTAINERS)" \ + --license "BSD" \ + --description "core vnoded/vcmd and system dependencies" \ + --url https://github.com/coreemu/core \ + --vendor "$(PACKAGE_VENDOR)" \ + -p core_VERSION_ARCH.rpm \ + -v $(PACKAGE_VERSION) \ + --rpm-init package/core-daemon \ + --after-install package/after-install.sh \ + --after-remove package/after-remove.sh \ + -d "ethtool" \ + -d "tk" \ -d "procps-ng" \ -d "bash >= 3.0" \ - -d "bridge-utils" \ -d "ebtables" \ -d "iproute" \ -d "libev" \ -d "net-tools" \ - -d "python >= 2.7, python < 3.0" \ - netns/setup.py daemon/setup.py + -d "nftables" \ + netns/vnoded=/usr/bin/ \ + netns/vcmd=/usr/bin/ \ + package/etc/core.conf=/etc/core/ \ + package/etc/logging.conf=/etc/core/ \ + package/examples=/opt/core/ \ + daemon/dist/core-$(PACKAGE_VERSION)-py3-none-any.whl=/opt/core/ endef -define fpm-daemon-deb = -fpm -s python -t deb \ - -p NAME_$1_VERSION_ARCH.deb \ - --python-install-bin $(bindir) \ - --python-install-data $(prefix) \ - --python-install-lib $(pythondir) \ - $2 $3 \ +define fpm-deb = +fpm -s dir -t deb -n core \ -m "$(PACKAGE_MAINTAINERS)" \ + --license "BSD" \ + --description "core vnoded/vcmd and system dependencies" \ + --url https://github.com/coreemu/core \ --vendor "$(PACKAGE_VENDOR)" \ + -p core_VERSION_ARCH.deb \ + -v $(PACKAGE_VERSION) \ + --deb-systemd package/core-daemon.service \ + --deb-no-default-config-files \ + --after-install package/after-install.sh \ + --after-remove package/after-remove.sh \ + -d "ethtool" \ + -d "tk" \ + -d "libtk-img" \ -d "procps" \ -d "libc6 >= 2.14" \ -d "bash >= 3.0" \ - -d "bridge-utils" \ -d "ebtables" \ -d "iproute2" \ -d "libev4" \ - -d "python (>= 2.7), python (<< 3.0)" \ - --deb-recommends quagga \ - netns/setup.py daemon/setup.py + -d "nftables" \ + netns/vnoded=/usr/bin/ \ + netns/vcmd=/usr/bin/ \ + package/etc/core.conf=/etc/core/ \ + package/etc/logging.conf=/etc/core/ \ + package/examples=/opt/core/ \ + daemon/dist/core-$(PACKAGE_VERSION)-py3-none-any.whl=/opt/core/ endef .PHONY: fpm fpm: clean-local-fpm - $(MAKE) -C gui install DESTDIR=$(DESTDIR) - $(call fpm-gui,rpm) - $(call fpm-gui,deb,-d "libtk-img") - $(call fpm-python,rpm,ns3/setup.py) - $(call fpm-python,deb,ns3/setup.py) - $(call fpm-daemon-rpm) - $(call fpm-daemon-deb,sysv,--deb-init,scripts/core-daemon) - $(call fpm-daemon-deb,systemd,--deb-systemd,scripts/core-daemon.service) + cd daemon && poetry build -f wheel + $(call fpm-deb) + $(call fpm-rpm) + $(call fpm-distributed-deb) + $(call fpm-distributed-rpm) .PHONY: clean-local-fpm clean-local-fpm: @@ -136,24 +170,12 @@ define change-files = $(info creating file $1 from $1.in) @$(SED) -e 's,[@]sbindir[@],$(sbindir),g' \ -e 's,[@]bindir[@],$(bindir),g' \ - -e 's,[@]pythondir[@],$(pythondir),g' \ - -e 's,[@]PYTHON[@],$(PYTHON),g' \ -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ -e 's,[@]PACKAGE_DATE[@],$(PACKAGE_DATE),g' \ -e 's,[@]CORE_LIB_DIR[@],$(CORE_LIB_DIR),g' \ -e 's,[@]CORE_STATE_DIR[@],$(CORE_STATE_DIR),g' \ -e 's,[@]CORE_DATA_DIR[@],$(CORE_DATA_DIR),g' \ -e 's,[@]CORE_CONF_DIR[@],$(CORE_CONF_DIR),g' \ - -e 's,[@]CORE_GUI_CONF_DIR[@],$(CORE_GUI_CONF_DIR),g' \ - -e 's,[@]brctl_path[@],$(brctl_path),g' \ - -e 's,[@]sysctl_path[@],$(sysctl_path),g' \ - -e 's,[@]ip_path[@],$(ip_path),g' \ - -e 's,[@]tc_path[@],$(tc_path),g' \ - -e 's,[@]ebtables_path[@],$(ebtables_path),g' \ - -e 's,[@]mount_path[@],$(mount_path),g' \ - -e 's,[@]umount_path[@],$(umount_path),g' \ - -e 's,[@]ovs_vs_path[@],$(ovs_vs_path),g' \ - -e 's,[@]ovs_of_path[@],$(ovs_of_path),g' \ < $1.in > $1 endef @@ -161,10 +183,8 @@ all: change-files .PHONY: change-files change-files: - $(call change-files,gui/core-gui) - $(call change-files,scripts/core-daemon.service) - $(call change-files,scripts/core-daemon) $(call change-files,daemon/core/constants.py) + $(call change-files,netns/setup.py) CORE_DOC_SRC = core-python-$(PACKAGE_VERSION) .PHONY: doc diff --git a/README.md b/README.md index 25ffc6d3..efab2e70 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,107 @@ +# Index +- CORE +- Docker Setup + - Precompiled container image + - Build container image from source + - Adding extra packages + +- Useful commands +- License + # CORE CORE: Common Open Research Emulator -Copyright (c)2005-2018 the Boeing Company. +Copyright (c)2005-2022 the Boeing Company. See the LICENSE file included in this distribution. -## About +# Docker Setup -The Common Open Research Emulator (CORE) is a tool for emulating -networks on one or more machines. You can connect these emulated -networks to live networks. CORE consists of a GUI for drawing -topologies of lightweight virtual machines, and Python modules for -scripting network emulation. +Here you have 2 choices -## Documentation and Examples +## Precompiled container image -* Documentation hosted on GitHub - * http://coreemu.github.io/core/ -* Basic Script Examples - * [Examples](daemon/examples/api) -* Custom Service Example - * [sample.py](daemon/examples/myservices/sample.py) -* Custom Emane Model Example - * [examplemodel.py](daemon/examples/myemane/examplemodel.py) +```bash -## Support +# Start container +sudo docker run -itd --name core -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw --privileged --restart unless-stopped git.olympuslab.net/afonso/core-extra:latest -We are leveraging Discord for persistent chat rooms, voice chat, and -GitHub integration. This allows for more dynamic conversations and the -capability to respond faster. Feel free to join us at the link below. -https://discord.gg/AKd7kmP +``` +## Build container image from source -You can also get help with questions, comments, or trouble, by using -the CORE mailing lists: +```bash +# Clone the repo +git clone https://gitea.olympuslab.net/afonso/core-extra.git -* [core-users](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-users) for general comments and questions -* [core-dev](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-dev) for bugs, compile errors, and other development issues +# cd into the directory +cd core-extra -## Building CORE +# build the docker image +sudo docker build -t core-extra . + +# start container +sudo docker run -itd --name core -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw --privileged --restart unless-stopped core-extra -```shell -./bootstrap.sh -./configure -make -sudo make install ``` -Building Documentation ----------------------- +### Adding extra packages + +To add extra packages you must modify the Dockerfile and then compile the docker image. +If you install it after starting the container it will, by docker nature, be reverted on the next boot of the container. + +# Useful commands + +I have the following functions on my fish shell +to help me better use core + +THIS ONLY WORKS ON FISH, MODIFY FOR BASH OR ZSH + +```fish + +# RUN CORE GUI +function core + xhost +local:root + sudo docker exec -it core core-gui +end + +# RUN BASH INSIDE THE CONTAINER +function core-bash + sudo docker exec -it core /bin/bash +end + + +# LAUNCH NODE BASH ON THE HOST MACHINE +function launch-term --argument nodename + sudo docker exec -it core xterm -bg black -fg white -fa 'DejaVu Sans Mono' -fs 16 -e vcmd -c /tmp/pycore.1/$nodename -- /bin/bash +end + +#TO RUN ANY OTHER COMMAND +sudo docker exec -it core COMAND_GOES_HERE -```shell -./bootstrap.sh -./configure -make doc ``` -Building Packages ------------------ +## LICENSE -Install fpm: http://fpm.readthedocs.io/en/latest/installing.html +Copyright (c) 2005-2018, the Boeing Company. -Build package commands, DESTDIR is used for gui packaging only +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: -```shell -./bootstrap.sh -./configure -make -mkdir /tmp/core-gui -make fpm DESTDIR=/tmp/core-gui -``` +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -This will produce: - -* CORE GUI rpm/deb files - * core-gui_$VERSION_$ARCH -* CORE ns3 rpm/deb files - * python-core-ns3_$VERSION_$ARCH -* CORE python rpm/deb files for SysV and systemd service types - * python-core-sysv_$VERSION_$ARCH - * python-core-systemd_$VERSION_$ARCH - -Running CORE ------------- - -First start the CORE services: - -```shell -# sysv -sudo service core-daemon start -# systemd -sudo systemctl start core-daemon -``` - -This automatically runs the core-daemon program. -Assuming the GUI is in your PATH, run the CORE GUI by typing the following: - -```shell -core-gui -``` - -This launches the CORE GUI. You do not need to run the GUI as root. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bootstrap.sh b/bootstrap.sh index ab3d741c..25fdecfd 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,9 +1,5 @@ #!/bin/sh # -# (c)2010-2012 the Boeing Company -# -# author: Jeff Ahrenholz -# # Bootstrap the autoconf system. # diff --git a/configure.ac b/configure.ac index 80e45840..4e56507a 100644 --- a/configure.ac +++ b/configure.ac @@ -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, 5.2, core-dev@nrl.navy.mil) +AC_INIT(core, 9.0.3) # autoconf and automake initialization AC_CONFIG_SRCDIR([netns/version.h.in]) @@ -14,7 +14,7 @@ AM_INIT_AUTOMAKE([tar-ustar]) # define variables used for packaging and date display PACKAGE_DATE=m4_esyscmd_s([date +%Y%m%d]) PACKAGE_VENDOR="CORE Developers" -PACKAGE_MAINTAINERS="$PACKAGE_VENDOR <$PACKAGE_BUGREPORT>" +PACKAGE_MAINTAINERS="$PACKAGE_VENDOR" # core specific variables CORE_LIB_DIR="\${prefix}/lib/core" @@ -30,19 +30,25 @@ AC_SUBST(CORE_CONF_DIR) AC_SUBST(CORE_DATA_DIR) AC_SUBST(CORE_STATE_DIR) -# CORE GUI configuration files and preferences in CORE_GUI_CONF_DIR -# scenario files in ~/.core/configs/ -AC_ARG_WITH([guiconfdir], - [AS_HELP_STRING([--with-guiconfdir=dir], - [specify GUI configuration directory])], - [CORE_GUI_CONF_DIR="$with_guiconfdir"], - [CORE_GUI_CONF_DIR="\$\${HOME}/.core"]) -AC_SUBST(CORE_GUI_CONF_DIR) -AC_ARG_ENABLE([gui], - [AS_HELP_STRING([--enable-gui[=ARG]], - [build and install the GUI (default is yes)])], - [], [enable_gui=yes]) -AC_SUBST(enable_gui) +# documentation option +AC_ARG_ENABLE([docs], + [AS_HELP_STRING([--enable-docs[=ARG]], + [build python documentation (default is no)])], + [], [enable_docs=no]) +AC_SUBST(enable_docs) + +# python option +AC_ARG_ENABLE([python], + [AS_HELP_STRING([--enable-python[=ARG]], + [build and install the python bindings (default is yes)])], + [], [enable_python=yes]) +AC_SUBST(enable_python) +if test "x$enable_python" = "xyes" ; then + want_python=yes +else + want_python=no +fi + AC_ARG_ENABLE([daemon], [AS_HELP_STRING([--enable-daemon[=ARG]], [build and install the daemon with Python modules @@ -50,6 +56,13 @@ AC_ARG_ENABLE([daemon], [], [enable_daemon=yes]) AC_SUBST(enable_daemon) +AC_ARG_ENABLE([vnodedonly], + [AS_HELP_STRING([--enable-vnodedonly[=ARG]], + [only try to build vnoded and vcmd container utils + (default is no)])], + [enable_vnodedonly=yes], [enable_vnodedonly=no]) +AC_SUBST(enable_vnodedonly) + SEARCHPATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin" # default compiler flags @@ -70,8 +83,62 @@ if test "x$enable_daemon" = "xyes"; then want_python=yes want_linux_netns=yes - # Checks for libraries. - AC_CHECK_LIB([netgraph], [NgMkSockNode]) + AM_PATH_PYTHON(3.9) + AS_IF([$PYTHON -m grpc_tools.protoc -h &> /dev/null], [], [AC_MSG_ERROR([please install python grpcio-tools])]) + + AC_CHECK_PROG(sysctl_path, sysctl, $as_dir, no, $SEARCHPATH) + if test "x$sysctl_path" = "xno" ; then + AC_MSG_ERROR([Could not locate sysctl (from procps package).]) + fi + + AC_CHECK_PROG(nftables_path, nft, $as_dir, no, $SEARCHPATH) + if test "x$nftables_path" = "xno" ; then + AC_MSG_ERROR([Could not locate nftables (from nftables package).]) + fi + + AC_CHECK_PROG(ip_path, ip, $as_dir, no, $SEARCHPATH) + if test "x$ip_path" = "xno" ; then + AC_MSG_ERROR([Could not locate ip (from iproute package).]) + fi + + AC_CHECK_PROG(tc_path, tc, $as_dir, no, $SEARCHPATH) + if test "x$tc_path" = "xno" ; then + AC_MSG_ERROR([Could not locate tc (from iproute package).]) + fi + + AC_CHECK_PROG(ethtool_path, ethtool, $as_dir, no, $SEARCHPATH) + if test "x$ethtool_path" = "xno" ; then + AC_MSG_ERROR([Could not locate ethtool (from package ethtool)]) + fi + + AC_CHECK_PROG(mount_path, mount, $as_dir, no, $SEARCHPATH) + if test "x$mount_path" = "xno" ; then + AC_MSG_ERROR([Could not locate mount (from package mount)]) + fi + + AC_CHECK_PROG(umount_path, umount, $as_dir, no, $SEARCHPATH) + if test "x$umount_path" = "xno" ; then + AC_MSG_ERROR([Could not locate umount (from package mount)]) + fi + + AC_CHECK_PROG(convert, convert, yes, no, $SEARCHPATH) + if test "x$convert" = "xno" ; then + AC_MSG_WARN([Could not locate ImageMagick convert.]) + fi + + AC_CHECK_PROG(ovs_vs_path, ovs-vsctl, $as_dir, no, $SEARCHPATH) + if test "x$ovs_vs_path" = "xno" ; then + AC_MSG_WARN([Could not locate ovs-vsctl cannot use OVS mode]) + fi + + AC_CHECK_PROG(ovs_of_path, ovs-ofctl, $as_dir, no, $SEARCHPATH) + if test "x$ovs_of_path" = "xno" ; then + AC_MSG_WARN([Could not locate ovs-ofctl cannot use OVS mode]) + fi +fi + +if [ test "x$enable_daemon" = "xyes" || test "x$enable_vnodedonly" = "xyes" ] ; then + want_linux_netns=yes # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h stdint.h stdlib.h string.h sys/ioctl.h sys/mount.h sys/socket.h sys/time.h termios.h unistd.h]) @@ -91,51 +158,6 @@ if test "x$enable_daemon" = "xyes"; then AC_FUNC_REALLOC AC_CHECK_FUNCS([atexit dup2 gettimeofday memset socket strerror uname]) - AM_PATH_PYTHON(2.7) - - AC_CHECK_PROG(brctl_path, brctl, $as_dir, no, $SEARCHPATH) - if test "x$brctl_path" = "xno" ; then - AC_MSG_ERROR([Could not locate brctl (from bridge-utils package).]) - fi - AC_CHECK_PROG(sysctl_path, sysctl, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ebtables_path, ebtables, $as_dir, no, $SEARCHPATH) - if test "x$ebtables_path" = "xno" ; then - AC_MSG_ERROR([Could not locate ebtables (from ebtables package).]) - fi - AC_CHECK_PROG(ip_path, ip, $as_dir, no, $SEARCHPATH) - if test "x$ip_path" = "xno" ; then - AC_MSG_ERROR([Could not locate ip (from iproute package).]) - fi - AC_CHECK_PROG(tc_path, tc, $as_dir, no, $SEARCHPATH) - if test "x$tc_path" = "xno" ; then - AC_MSG_ERROR([Could not locate tc (from iproute package).]) - fi - AC_CHECK_PROG(mount_path, mount, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(umount_path, umount, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(convert, convert, yes, no, $SEARCHPATH) - if test "x$convert" = "xno" ; then - AC_MSG_WARN([Could not locate ImageMagick convert.]) - fi - AC_CHECK_PROG(ovs_vs_path, ovs-vsctl, $as_dir, no, $SEARCHPATH) - if test "x$ovs_vs_path" = "xno" ; then - AC_MSG_WARN([Could not locate ovs-vsctl cannot use OVS nodes]) - fi - AC_CHECK_PROG(ovs_of_path, ovs-ofctl, $as_dir, no, $SEARCHPATH) - if test "x$ovs_of_path" = "xno" ; then - AC_MSG_WARN([Could not locate ovs-ofctl cannot use OVS nodes]) - fi - - CFLAGS_save=$CFLAGS - CPPFLAGS_save=$CPPFLAGS - if test "x$PYTHON_INCLUDE_DIR" = "x"; then - PYTHON_INCLUDE_DIR=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc()"` - fi - CFLAGS="-I$PYTHON_INCLUDE_DIR" - CPPFLAGS="-I$PYTHON_INCLUDE_DIR" - AC_CHECK_HEADERS([Python.h], [], - AC_MSG_ERROR([Python bindings require Python development headers (try installing your 'python-devel' or 'python-dev' package)])) - CFLAGS=$CFLAGS_save - CPPFLAGS=$CPPFLAGS_save PKG_CHECK_MODULES(libev, libev, AC_MSG_RESULT([found libev using pkgconfig OK]) AC_SUBST(libev_CFLAGS) @@ -148,52 +170,37 @@ if test "x$enable_daemon" = "xyes"; then AC_MSG_ERROR([Python bindings require libev (try installing your 'libev-devel' or 'libev-dev' package)]))) fi -AC_CHECK_PROG(help2man, help2man, yes, no, $SEARCHPATH) +want_docs=no +if [test "x$want_python" = "xyes" && test "x$enable_docs" = "xyes"] ; then + AC_CHECK_PROG(help2man, help2man, yes, no, $SEARCHPATH) -if test "x$help2man" = "xno" ; then + if test "x$help2man" = "xno" ; then AC_MSG_WARN([Could not locate help2man.]) want_docs_missing="$want_docs_missing help2man" + fi + + if test "x$want_docs_missing" = "x" ; then + want_docs=yes + else + AC_MSG_ERROR([Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built.]) + want_docs=no + fi + + # check for sphinx required during make + AC_CHECK_PROG(sphinxapi_path, sphinx-apidoc, $as_dir, no, $SEARCHPATH) + if test "x$sphinxapi_path" = "xno" ; then + AC_MSG_ERROR(["Could not locate sphinx-apidoc, install python3 -m pip install sphinx"]) + want_docs=no + fi + AS_IF([$PYTHON -c "import sphinx_rtd_theme" &> /dev/null], [], [AC_MSG_ERROR([doc dependency missing, please install python3 -m pip install sphinx-rtd-theme])]) fi -if test "x$want_docs_missing" = "x" ; then - want_docs=yes -else - AC_MSG_WARN([Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built.]) - want_docs=no -fi - -# check for sphinx required during make -AC_CHECK_PROG(sphinxapi_path, sphinx-apidoc, $as_dir, no, $SEARCHPATH) -if test "x$sphinxapi_path" = "xno" ; then - AC_MSG_ERROR(["Could not location sphinx-apidoc, from the python-sphinx package"]) -fi - -#AC_PATH_PROGS(tcl_path, [tclsh tclsh8.5 tclsh8.4], no) -#if test "x$tcl_path" = "xno" ; then -# AC_MSG_ERROR([Could not locate tclsh. Please install Tcl/Tk.]) -#fi - -#AC_PATH_PROGS(wish_path, [wish wish8.5 wish8.4], no) -#if test "x$wish_path" = "xno" ; then -# AC_MSG_ERROR([Could not locate wish. Please install Tcl/Tk.]) -#fi - -AC_ARG_WITH([startup], - [AS_HELP_STRING([--with-startup=option], - [option=systemd,suse,none to install systemd/SUSE init scripts])], - [with_startup=$with_startup], - [with_startup=initd]) -AC_SUBST(with_startup) -AC_MSG_RESULT([using startup option $with_startup]) - # Variable substitutions -AM_CONDITIONAL(WANT_GUI, test x$enable_gui = xyes) AM_CONDITIONAL(WANT_DAEMON, test x$enable_daemon = xyes) AM_CONDITIONAL(WANT_DOCS, test x$want_docs = xyes) AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes) AM_CONDITIONAL(WANT_NETNS, test x$want_linux_netns = xyes) -AM_CONDITIONAL(WANT_INITD, test x$with_startup = xinitd) -AM_CONDITIONAL(WANT_SYSTEMD, test x$with_startup = xsystemd) +AM_CONDITIONAL(WANT_VNODEDONLY, test x$enable_vnodedonly = xyes) if test $cross_compiling = no; then AM_MISSING_PROG(HELP2MAN, help2man) @@ -203,19 +210,14 @@ fi # Output files AC_CONFIG_FILES([Makefile - gui/version.tcl - gui/Makefile - gui/icons/Makefile - scripts/Makefile - scripts/perf/Makefile man/Makefile docs/Makefile daemon/Makefile daemon/doc/Makefile daemon/doc/conf.py + daemon/proto/Makefile netns/Makefile - netns/version.h - ns3/Makefile],) + netns/version.h],) AC_OUTPUT # Summary text @@ -229,20 +231,12 @@ Build: Prefix: ${prefix} Exec Prefix: ${exec_prefix} -GUI: - GUI path: ${CORE_LIB_DIR} - GUI config: ${CORE_GUI_CONF_DIR} - Daemon: Daemon path: ${bindir} Daemon config: ${CORE_CONF_DIR} - Python modules: ${pythondir} - Logs: ${CORE_STATE_DIR}/log - -Startup: ${with_startup} + Python: ${PYTHON} Features to build: - Build GUI: ${enable_gui} Build Daemon: ${enable_daemon} Documentation: ${want_docs} diff --git a/corefx/pom.xml b/corefx/pom.xml deleted file mode 100644 index 4b6653a1..00000000 --- a/corefx/pom.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - 4.0.0 - - com.core - corefx - 1.0-SNAPSHOT - - - UTF-8 - 1.8 - 1.8 - 2.1.1 - 2.9.6 - - - - - net.sf.jung - jung-api - ${jung.version} - - - net.sf.jung - jung-graph-impl - ${jung.version} - - - net.sf.jung - jung-algorithms - ${jung.version} - - - net.sf.jung - jung-io - ${jung.version} - - - net.sf.jung - jung-visualization - ${jung.version} - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - com.squareup.okhttp3 - okhttp - 3.11.0 - - - org.apache.logging.log4j - log4j-api - 2.9.0 - - - org.apache.logging.log4j - log4j-core - 2.9.0 - - - io.socket - socket.io-client - 0.8.3 - - - org.projectlombok - lombok - 1.18.0 - provided - - - commons-net - commons-net - 3.6 - - - com.jfoenix - jfoenix - 8.0.7 - - - - - - - com.zenjava - javafx-maven-plugin - 8.8.3 - - com.core.Main - - - - - \ No newline at end of file diff --git a/corefx/src/main/java/com/core/Controller.java b/corefx/src/main/java/com/core/Controller.java deleted file mode 100644 index 78e7791e..00000000 --- a/corefx/src/main/java/com/core/Controller.java +++ /dev/null @@ -1,543 +0,0 @@ -package com.core; - -import com.core.client.ICoreClient; -import com.core.client.rest.CoreRestClient; -import com.core.data.*; -import com.core.graph.NetworkGraph; -import com.core.ui.*; -import com.core.ui.dialogs.*; -import com.core.utils.ConfigUtils; -import com.core.utils.Configuration; -import com.core.utils.NodeTypeConfig; -import com.core.websocket.CoreWebSocket; -import com.jfoenix.controls.JFXDecorator; -import com.jfoenix.controls.JFXProgressBar; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.concurrent.Task; -import javafx.embed.swing.SwingNode; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.control.CheckMenuItem; -import javafx.scene.control.MenuItem; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; -import javafx.stage.FileChooser; -import javafx.stage.Stage; -import lombok.Data; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.awt.event.ItemEvent; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; - -@Data -public class Controller implements Initializable { - private static final Logger logger = LogManager.getLogger(); - @FXML private StackPane stackPane; - @FXML private BorderPane borderPane; - @FXML private VBox top; - @FXML private VBox bottom; - @FXML private SwingNode swingNode; - @FXML private MenuItem saveXmlMenuItem; - @FXML private JFXProgressBar progressBar; - @FXML private CheckMenuItem throughputMenuItem; - - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); - private final Map mobilityScripts = new HashMap<>(); - private final Map mobilityPlayerDialogs = new HashMap<>(); - private Application application; - private JFXDecorator decorator; - private Stage window; - private Configuration configuration; - private Map> defaultServices = new HashMap<>(); - - // core client utilities - private ICoreClient coreClient = new CoreRestClient(); - private CoreWebSocket coreWebSocket; - - // ui elements - private NetworkGraph networkGraph = new NetworkGraph(this); - private AnnotationToolbar annotationToolbar = new AnnotationToolbar(networkGraph); - private NodeDetails nodeDetails = new NodeDetails(this); - private LinkDetails linkDetails = new LinkDetails(this); - private GraphToolbar graphToolbar = new GraphToolbar(this); - - // dialogs - private SessionsDialog sessionsDialog = new SessionsDialog(this); - private ServiceDialog serviceDialog = new ServiceDialog(this); - private NodeServicesDialog nodeServicesDialog = new NodeServicesDialog(this); - private NodeEmaneDialog nodeEmaneDialog = new NodeEmaneDialog(this); - private NodeWlanDialog nodeWlanDialog = new NodeWlanDialog(this); - private ConfigDialog configDialog = new ConfigDialog(this); - private HooksDialog hooksDialog = new HooksDialog(this); - private MobilityDialog mobilityDialog = new MobilityDialog(this); - private ChartDialog chartDialog = new ChartDialog(this); - private NodeTypesDialog nodeTypesDialog = new NodeTypesDialog(this); - private BackgroundDialog backgroundDialog = new BackgroundDialog(this); - private LocationDialog locationDialog = new LocationDialog(this); - private GeoDialog geoDialog = new GeoDialog(this); - private ConnectDialog connectDialog = new ConnectDialog(this); - private GuiPreferencesDialog guiPreferencesDialog = new GuiPreferencesDialog(this); - private NodeTypeCreateDialog nodeTypeCreateDialog = new NodeTypeCreateDialog(this); - - public void connectToCore(String address, int port) { - coreWebSocket.stop(); - - ExecutorService executorService = Executors.newSingleThreadExecutor(); - executorService.submit(() -> { - try { - coreWebSocket.start(address, port); - coreClient.setConnection(address, port); - initialJoin(); - } catch (IOException | URISyntaxException ex) { - Toast.error(String.format("Connection failure: %s", ex.getMessage()), ex); - Platform.runLater(() -> connectDialog.showDialog()); - } - }); - } - - private void initialJoin() throws IOException { - Map> serviceGroups = coreClient.getServices(); - logger.info("core services: {}", serviceGroups); - nodeServicesDialog.setServices(serviceGroups); - nodeTypeCreateDialog.setServices(serviceGroups); - - logger.info("initial core session join"); - List sessions = coreClient.getSessions(); - - logger.info("existing sessions: {}", sessions); - Integer sessionId; - if (sessions.isEmpty()) { - logger.info("creating initial session"); - SessionOverview sessionOverview = coreClient.createSession(); - sessionId = sessionOverview.getId(); - Toast.info(String.format("Created Session %s", sessionId)); - } else { - SessionOverview sessionOverview = sessions.get(0); - sessionId = sessionOverview.getId(); - Toast.info(String.format("Joined Session %s", sessionId)); - } - - joinSession(sessionId); - - // set emane models - List emaneModels = coreClient.getEmaneModels(); - nodeEmaneDialog.setModels(emaneModels); - } - - public void joinSession(Integer sessionId) throws IOException { - // clear graph - networkGraph.reset(); - - // clear out any previously set information - mobilityPlayerDialogs.clear(); - mobilityScripts.clear(); - mobilityDialog.setNode(null); - Platform.runLater(() -> borderPane.setRight(null)); - - // get session to join - Session session = coreClient.getSession(sessionId); - SessionState sessionState = SessionState.get(session.getState()); - - // update client to use this session - coreClient.updateSession(sessionId); - coreClient.updateState(sessionState); - - // display all nodes - logger.info("joining core session({}) state({}): {}", sessionId, sessionState, session); - for (CoreNode node : session.getNodes()) { - NodeType nodeType = NodeType.find(node.getType(), node.getModel()); - if (nodeType == null) { - logger.info(String.format("failed to find node type(%s) model(%s): %s", - node.getType(), node.getModel(), node.getName())); - continue; - } - - node.setNodeType(nodeType); - networkGraph.addNode(node); - } - - // display all links - for (CoreLink link : session.getLinks()) { - if (link.getInterfaceOne() != null || link.getInterfaceTwo() != null) { - link.setType(LinkTypes.WIRED.getValue()); - } - - networkGraph.addLink(link); - } - - // refresh graph - networkGraph.getGraphViewer().repaint(); - - // update other components for new session - graphToolbar.setRunButton(coreClient.isRunning()); - hooksDialog.updateHooks(); - - // update session default services - setCoreDefaultServices(); - - // retrieve current mobility script configurations and show dialogs - Map mobilityConfigMap = coreClient.getMobilityConfigs(); - mobilityScripts.putAll(mobilityConfigMap); - showMobilityScriptDialogs(); - - Platform.runLater(() -> decorator.setTitle(String.format("CORE (Session %s)", sessionId))); - } - - public boolean startSession() throws IOException { - // force nodes to get latest positions - networkGraph.updatePositions(); - - // retrieve items for creation/start - Collection nodes = networkGraph.getGraph().getVertices(); - Collection links = networkGraph.getGraph().getEdges(); - List hooks = hooksDialog.getHooks(); - - // start/create session - progressBar.setVisible(true); - boolean result = coreClient.start(nodes, links, hooks); - progressBar.setVisible(false); - if (result) { - showMobilityScriptDialogs(); - saveXmlMenuItem.setDisable(false); - } - return result; - } - - public boolean stopSession() throws IOException { - // clear out any drawn wireless links - List wirelessLinks = networkGraph.getGraph().getEdges().stream() - .filter(CoreLink::isWireless) - .collect(Collectors.toList()); - wirelessLinks.forEach(networkGraph::removeWirelessLink); - networkGraph.getGraphViewer().repaint(); - - // stop session - progressBar.setVisible(true); - boolean result = coreClient.stop(); - progressBar.setVisible(false); - if (result) { - saveXmlMenuItem.setDisable(true); - } - return result; - } - - public void handleThroughputs(Throughputs throughputs) { - for (InterfaceThroughput interfaceThroughput : throughputs.getInterfaces()) { - int nodeId = interfaceThroughput.getNode(); - CoreNode node = networkGraph.getVertex(nodeId); - Collection links = networkGraph.getGraph().getIncidentEdges(node); - int interfaceId = interfaceThroughput.getNodeInterface(); - for (CoreLink link : links) { - if (nodeId == link.getNodeOne()) { - if (interfaceId == link.getInterfaceOne().getId()) { - link.setThroughput(interfaceThroughput.getThroughput()); - } - } else { - if (interfaceId == link.getInterfaceTwo().getId()) { - link.setThroughput(interfaceThroughput.getThroughput()); - } - } - } - } - networkGraph.getGraphViewer().repaint(); - } - - private void setCoreDefaultServices() { - try { - coreClient.setDefaultServices(defaultServices); - } catch (IOException ex) { - Toast.error("Error updating core default services", ex); - } - } - - public void updateNodeTypes() { - graphToolbar.setupNodeTypes(); - setCoreDefaultServices(); - try { - ConfigUtils.save(configuration); - } catch (IOException ex) { - Toast.error("Error saving configuration", ex); - } - } - - public void deleteNode(CoreNode node) { - networkGraph.removeNode(node); - CoreNode mobilityNode = mobilityDialog.getNode(); - if (mobilityNode != null && mobilityNode.getId().equals(node.getId())) { - mobilityDialog.setNode(null); - } - } - - void setWindow(Stage window) { - this.window = window; - sessionsDialog.setOwner(window); - hooksDialog.setOwner(window); - nodeServicesDialog.setOwner(window); - serviceDialog.setOwner(window); - nodeWlanDialog.setOwner(window); - nodeEmaneDialog.setOwner(window); - configDialog.setOwner(window); - mobilityDialog.setOwner(window); - nodeTypesDialog.setOwner(window); - backgroundDialog.setOwner(window); - locationDialog.setOwner(window); - connectDialog.setOwner(window); - guiPreferencesDialog.setOwner(window); - nodeTypeCreateDialog.setOwner(window); - } - - private void showMobilityScriptDialogs() { - for (Map.Entry entry : mobilityScripts.entrySet()) { - Integer nodeId = entry.getKey(); - CoreNode node = networkGraph.getVertex(nodeId); - MobilityConfig mobilityConfig = entry.getValue(); - Platform.runLater(() -> { - MobilityPlayerDialog mobilityPlayerDialog = new MobilityPlayerDialog(this, node); - mobilityPlayerDialog.setOwner(window); - mobilityPlayerDialogs.put(nodeId, mobilityPlayerDialog); - mobilityPlayerDialog.showDialog(mobilityConfig); - }); - } - } - - @FXML - private void onCoreMenuConnect(ActionEvent event) { - logger.info("showing connect!"); - connectDialog.showDialog(); - } - - @FXML - private void onOptionsMenuNodeTypes(ActionEvent event) { - nodeTypesDialog.showDialog(); - } - - @FXML - private void onOptionsMenuBackground(ActionEvent event) { - backgroundDialog.showDialog(); - } - - @FXML - private void onOptionsMenuLocation(ActionEvent event) { - locationDialog.showDialog(); - } - - @FXML - private void onOptionsMenuPreferences(ActionEvent event) { - guiPreferencesDialog.showDialog(); - } - - @FXML - private void onHelpMenuWebsite(ActionEvent event) { - application.getHostServices().showDocument("https://github.com/coreemu/core"); - } - - @FXML - private void onHelpMenuDocumentation(ActionEvent event) { - application.getHostServices().showDocument("http://coreemu.github.io/core/"); - } - - @FXML - private void onHelpMenuMailingList(ActionEvent event) { - application.getHostServices().showDocument("https://publists.nrl.navy.mil/mailman/listinfo/core-users"); - } - - @FXML - private void onOpenXmlAction() { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Open Session"); - fileChooser.setInitialDirectory(new File(configuration.getXmlPath())); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("XML", "*.xml")); - try { - File file = fileChooser.showOpenDialog(window); - if (file != null) { - openXml(file); - } - } catch (IllegalArgumentException ex) { - Toast.error(String.format("Invalid XML directory: %s", configuration.getXmlPath())); - } - } - - private void openXml(File file) { - logger.info("opening session xml: {}", file.getPath()); - try { - SessionOverview sessionOverview = coreClient.openSession(file); - Integer sessionId = sessionOverview.getId(); - joinSession(sessionId); - Toast.info(String.format("Joined Session %s", sessionId)); - } catch (IOException ex) { - Toast.error("Error opening session xml", ex); - } - } - - @FXML - private void onSaveXmlAction() { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Save Session"); - fileChooser.setInitialFileName("session.xml"); - fileChooser.setInitialDirectory(new File(configuration.getXmlPath())); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("XML", "*.xml")); - File file = fileChooser.showSaveDialog(window); - if (file != null) { - logger.info("saving session xml: {}", file.getPath()); - try { - coreClient.saveSession(file); - } catch (IOException ex) { - Toast.error("Error saving session xml", ex); - } - } - } - - @FXML - private void onSessionMenu(ActionEvent event) { - logger.info("sessions menu clicked"); - try { - sessionsDialog.showDialog(); - } catch (IOException ex) { - Toast.error("Error retrieving sessions", ex); - } - } - - @FXML - private void onSessionNodesMenu(ActionEvent event) { - - } - - @FXML - private void onSessionHooksMenu(ActionEvent event) { - hooksDialog.showDialog(); - } - - @FXML - private void onSessionOptionsMenu(ActionEvent event) { - try { - List configGroups = coreClient.getSessionConfig(); - configDialog.showDialog("Session Options", configGroups, () -> { - List options = configDialog.getOptions(); - try { - boolean result = coreClient.setSessionConfig(options); - if (result) { - Toast.info("Session options saved"); - } else { - Toast.error("Failure to set session config"); - } - } catch (IOException ex) { - logger.error("error getting session config"); - } - }); - } catch (IOException ex) { - logger.error("error getting session config"); - } - } - - @FXML - private void onTestMenuCharts(ActionEvent event) { - chartDialog.show(); - } - - @FXML - private void onTestMenuGeo(ActionEvent event) { - geoDialog.showDialog(); - } - - @Override - public void initialize(URL location, ResourceBundle resources) { - coreWebSocket = new CoreWebSocket(this); - configuration = ConfigUtils.load(); - String address = configuration.getCoreAddress(); - int port = configuration.getCorePort(); - logger.info("core connection: {}:{}", address, port); - connectDialog.setAddress(address); - connectDialog.setPort(port); - connectToCore(address, port); - - logger.info("controller initialize"); - swingNode.setContent(networkGraph.getGraphViewer()); - - // update graph preferences - networkGraph.updatePreferences(configuration); - - // set node types / default services - graphToolbar.setupNodeTypes(); - defaultServices = configuration.getNodeTypeConfigs().stream() - .collect(Collectors.toMap(NodeTypeConfig::getModel, NodeTypeConfig::getServices)); - - // set graph toolbar - borderPane.setLeft(graphToolbar); - - // setup snackbar - Toast.setSnackbarRoot(stackPane); - - // setup throughput menu item - throughputMenuItem.setOnAction(event -> executorService.submit(new ChangeThroughputTask())); - - // node details - networkGraph.getGraphViewer().getPickedVertexState().addItemListener(event -> { - CoreNode node = (CoreNode) event.getItem(); - logger.info("picked: {}", node.getName()); - if (event.getStateChange() == ItemEvent.SELECTED) { - Platform.runLater(() -> { - nodeDetails.setNode(node); - borderPane.setRight(nodeDetails); - }); - } else { - Platform.runLater(() -> borderPane.setRight(null)); - } - }); - - // edge details - networkGraph.getGraphViewer().getPickedEdgeState().addItemListener(event -> { - CoreLink link = (CoreLink) event.getItem(); - logger.info("picked: {} - {}", link.getNodeOne(), link.getNodeTwo()); - if (event.getStateChange() == ItemEvent.SELECTED) { - Platform.runLater(() -> { - linkDetails.setLink(link); - borderPane.setRight(linkDetails); - }); - } else { - Platform.runLater(() -> borderPane.setRight(null)); - } - }); - } - - private class ChangeThroughputTask extends Task { - @Override - protected Boolean call() throws Exception { - if (throughputMenuItem.isSelected()) { - return coreClient.startThroughput(); - } else { - return coreClient.stopThroughput(); - } - } - - @Override - protected void succeeded() { - if (getValue()) { - if (throughputMenuItem.isSelected()) { - networkGraph.setShowThroughput(true); - } else { - networkGraph.setShowThroughput(false); - networkGraph.getGraph().getEdges().forEach(edge -> edge.setThroughput(0)); - networkGraph.getGraphViewer().repaint(); - } - } else { - Toast.error("Failure changing throughput"); - } - } - - @Override - protected void failed() { - Toast.error("Error changing throughput", new RuntimeException(getException())); - } - } -} diff --git a/corefx/src/main/java/com/core/Main.java b/corefx/src/main/java/com/core/Main.java deleted file mode 100644 index 4834278f..00000000 --- a/corefx/src/main/java/com/core/Main.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.core; - -import com.core.utils.ConfigUtils; -import com.jfoenix.controls.JFXDecorator; -import com.jfoenix.svg.SVGGlyphLoader; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.fxml.FXMLLoader; -import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.text.Font; -import javafx.stage.Stage; - -import java.nio.file.Path; -import java.nio.file.Paths; - -public class Main extends Application { - private static final Path LOG_FILE = Paths.get(System.getProperty("user.home"), ".core", "core.log"); - - @Override - public void start(Stage window) throws Exception { - // set core dir property for logging - System.setProperty("core_log", LOG_FILE.toString()); - - // check for and create gui home directory - ConfigUtils.checkHomeDirectory(); - - // load svg icons - SVGGlyphLoader.loadGlyphsFont(getClass().getResourceAsStream("/icons/icomoon_material.svg"), - "icomoon.svg"); - - // load font - Font.loadFont(getClass().getResourceAsStream("/font/roboto/Roboto-Regular.ttf"), 10); - - // load main fxml - FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/main.fxml")); - Parent root = loader.load(); - - // window decorator - JFXDecorator decorator = new JFXDecorator(window, root); - decorator.setCustomMaximize(true); - decorator.setMaximized(true); - decorator.setTitle("CORE"); - Image coreIcon = new Image(getClass().getResourceAsStream("/core-icon.png")); - decorator.setGraphic(new ImageView(coreIcon)); - window.getIcons().add(coreIcon); - - // create scene and set as current scene within window - Scene scene = new Scene(decorator); - scene.getStylesheets().add(getClass().getResource("/css/main.css").toExternalForm()); - window.setScene(scene); - - // update controller - Controller controller = loader.getController(); - controller.setApplication(this); - controller.setWindow(window); - controller.setDecorator(decorator); - - // configure window - window.setOnCloseRequest(event -> { - Platform.exit(); - System.exit(0); - }); - window.show(); - } - - public static void main(String[] args) { - launch(args); - } -} diff --git a/corefx/src/main/java/com/core/client/ICoreClient.java b/corefx/src/main/java/com/core/client/ICoreClient.java deleted file mode 100644 index fa06395d..00000000 --- a/corefx/src/main/java/com/core/client/ICoreClient.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.core.client; - -import com.core.client.rest.ServiceFile; -import com.core.client.rest.WlanConfig; -import com.core.data.*; - -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface ICoreClient { - void setConnection(String address, int port); - - boolean isLocalConnection(); - - Integer currentSession(); - - boolean startThroughput() throws IOException; - - boolean stopThroughput() throws IOException; - - void updateSession(Integer sessionId); - - void updateState(SessionState state); - - SessionOverview createSession() throws IOException; - - boolean deleteSession(Integer sessionId) throws IOException; - - List getSessions() throws IOException; - - Session getSession(Integer sessionId) throws IOException; - - boolean start(Collection nodes, Collection links, List hooks) throws IOException; - - boolean stop() throws IOException; - - boolean setState(SessionState state) throws IOException; - - Map> getServices() throws IOException; - - Map> getDefaultServices() throws IOException; - - boolean setDefaultServices(Map> defaults) throws IOException; - - CoreService getService(CoreNode node, String serviceName) throws IOException; - - boolean setService(CoreNode node, String serviceName, CoreService service) throws IOException; - - String getServiceFile(CoreNode node, String serviceName, String fileName) throws IOException; - - boolean startService(CoreNode node, String serviceName) throws IOException; - - boolean stopService(CoreNode node, String serviceName) throws IOException; - - boolean restartService(CoreNode node, String serviceName) throws IOException; - - boolean validateService(CoreNode node, String serviceName) throws IOException; - - boolean setServiceFile(CoreNode node, String serviceName, ServiceFile serviceFile) throws IOException; - - List getEmaneConfig(CoreNode node) throws IOException; - - List getEmaneModels() throws IOException; - - boolean setEmaneConfig(CoreNode node, List options) throws IOException; - - List getEmaneModelConfig(Integer id, String model) throws IOException; - - boolean setEmaneModelConfig(Integer id, String model, List options) throws IOException; - - boolean isRunning(); - - void saveSession(File file) throws IOException; - - SessionOverview openSession(File file) throws IOException; - - List getSessionConfig() throws IOException; - - boolean setSessionConfig(List configOptions) throws IOException; - - boolean createNode(CoreNode node) throws IOException; - - String nodeCommand(CoreNode node, String command) throws IOException; - - boolean editNode(CoreNode node) throws IOException; - - boolean deleteNode(CoreNode node) throws IOException; - - boolean createLink(CoreLink link) throws IOException; - - boolean editLink(CoreLink link) throws IOException; - - boolean createHook(Hook hook) throws IOException; - - List getHooks() throws IOException; - - WlanConfig getWlanConfig(CoreNode node) throws IOException; - - boolean setWlanConfig(CoreNode node, WlanConfig config) throws IOException; - - String getTerminalCommand(CoreNode node) throws IOException; - - Map getMobilityConfigs() throws IOException; - - boolean setMobilityConfig(CoreNode node, MobilityConfig config) throws IOException; - - MobilityConfig getMobilityConfig(CoreNode node) throws IOException; - - boolean mobilityAction(CoreNode node, String action) throws IOException; - - LocationConfig getLocationConfig() throws IOException; - - boolean setLocationConfig(LocationConfig config) throws IOException; -} diff --git a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java b/corefx/src/main/java/com/core/client/rest/CoreRestClient.java deleted file mode 100644 index 3e963583..00000000 --- a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java +++ /dev/null @@ -1,415 +0,0 @@ -package com.core.client.rest; - -import com.core.client.ICoreClient; -import com.core.data.*; -import com.core.utils.WebUtils; -import lombok.Data; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.IOException; -import java.util.*; - -@Data -public class CoreRestClient implements ICoreClient { - private static final Logger logger = LogManager.getLogger(); - private String address; - private int port; - private Integer sessionId; - private SessionState sessionState; - - @Override - public void setConnection(String address, int port) { - this.address = address; - this.port = port; - } - - @Override - public boolean isLocalConnection() { - return address.equals("127.0.0.1") || address.equals("localhost"); - } - - @Override - public Integer currentSession() { - return sessionId; - } - - @Override - public void updateState(SessionState state) { - sessionState = state; - } - - @Override - public void updateSession(Integer sessionId) { - this.sessionId = sessionId; - } - - private String getUrl(String path) { - return String.format("http://%s:%s/%s", address, port, path); - } - - @Override - public SessionOverview createSession() throws IOException { - String url = getUrl("sessions"); - return WebUtils.post(url, SessionOverview.class); - } - - @Override - public boolean deleteSession(Integer sessionId) throws IOException { - String path = String.format("sessions/%s", sessionId); - String url = getUrl(path); - return WebUtils.delete(url); - } - - public Map> getServices() throws IOException { - String url = getUrl("services"); - GetServices getServices = WebUtils.getJson(url, GetServices.class); - return getServices.getGroups(); - } - - @Override - public Session getSession(Integer sessionId) throws IOException { - String path = String.format("sessions/%s", sessionId); - String url = getUrl(path); - return WebUtils.getJson(url, Session.class); - } - - @Override - public List getSessions() throws IOException { - String url = getUrl("sessions"); - GetSessions getSessions = WebUtils.getJson(url, GetSessions.class); - return getSessions.getSessions(); - } - - @Override - public boolean start(Collection nodes, Collection links, List hooks) throws IOException { - boolean result = setState(SessionState.DEFINITION); - if (!result) { - return false; - } - - result = setState(SessionState.CONFIGURATION); - if (!result) { - return false; - } - - for (Hook hook : hooks) { - if (!createHook(hook)) { - return false; - } - } - - for (CoreNode node : nodes) { - // must pre-configure wlan nodes, if not already - if (node.getNodeType().getValue() == NodeType.WLAN) { - WlanConfig config = getWlanConfig(node); - setWlanConfig(node, config); - } - - if (!createNode(node)) { - return false; - } - } - - for (CoreLink link : links) { - if (!createLink(link)) { - return false; - } - } - - return setState(SessionState.INSTANTIATION); - } - - @Override - public boolean stop() throws IOException { - return setState(SessionState.SHUTDOWN); - } - - @Override - public boolean setState(SessionState state) throws IOException { - String url = getUrl(String.format("sessions/%s/state", sessionId)); - Map data = new HashMap<>(); - data.put("state", state.getValue()); - boolean result = WebUtils.putJson(url, data); - - if (result) { - sessionState = state; - } - return result; - } - - private boolean uploadFile(File file) throws IOException { - String url = getUrl("upload"); - return WebUtils.postFile(url, file); - } - - @Override - public boolean startThroughput() throws IOException { - String url = getUrl("throughput/start"); - return WebUtils.putJson(url); - } - - @Override - public boolean stopThroughput() throws IOException { - String url = getUrl("throughput/stop"); - return WebUtils.putJson(url); - } - - @Override - public Map> getDefaultServices() throws IOException { - String url = getUrl(String.format("sessions/%s/services/default", sessionId)); - GetDefaultServices getDefaultServices = WebUtils.getJson(url, GetDefaultServices.class); - return getDefaultServices.getDefaults(); - } - - @Override - public boolean setDefaultServices(Map> defaults) throws IOException { - String url = getUrl(String.format("sessions/%s/services/default", sessionId)); - return WebUtils.postJson(url, defaults); - } - - @Override - public CoreService getService(CoreNode node, String serviceName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s", sessionId, node.getId(), serviceName)); - return WebUtils.getJson(url, CoreService.class); - } - - @Override - public boolean setService(CoreNode node, String serviceName, CoreService service) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s", sessionId, node.getId(), serviceName)); - return WebUtils.putJson(url, service); - } - - @Override - public String getServiceFile(CoreNode node, String serviceName, String fileName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/file", sessionId, node.getId(), - serviceName)); - Map args = new HashMap<>(); - args.put("file", fileName); - return WebUtils.getJson(url, String.class, args); - } - - @Override - public boolean startService(CoreNode node, String serviceName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/start", sessionId, node.getId(), - serviceName)); - return WebUtils.putJson(url); - } - - @Override - public boolean stopService(CoreNode node, String serviceName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/stop", sessionId, node.getId(), - serviceName)); - return WebUtils.putJson(url); - } - - @Override - public boolean restartService(CoreNode node, String serviceName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/restart", sessionId, node.getId(), - serviceName)); - return WebUtils.putJson(url); - } - - @Override - public boolean validateService(CoreNode node, String serviceName) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/validate", sessionId, node.getId(), - serviceName)); - return WebUtils.putJson(url); - } - - @Override - public boolean setServiceFile(CoreNode node, String serviceName, ServiceFile serviceFile) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/services/%s/file", sessionId, node.getId(), - serviceName)); - return WebUtils.putJson(url, serviceFile); - } - - @Override - public List getEmaneModels() throws IOException { - String url = getUrl(String.format("sessions/%s/emane/models", sessionId)); - GetEmaneModels getEmaneModels = WebUtils.getJson(url, GetEmaneModels.class); - return getEmaneModels.getModels(); - } - - @Override - public List getEmaneModelConfig(Integer id, String model) throws IOException { - String url = getUrl(String.format("sessions/%s/emane/model/config", sessionId)); - Map args = new HashMap<>(); - args.put("node", id.toString()); - args.put("name", model); - GetConfig getConfig = WebUtils.getJson(url, GetConfig.class, args); - return getConfig.getGroups(); - } - - @Override - public List getEmaneConfig(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/emane/config", sessionId)); - Map args = new HashMap<>(); - args.put("node", node.getId().toString()); - GetConfig getConfig = WebUtils.getJson(url, GetConfig.class, args); - return getConfig.getGroups(); - } - - @Override - public boolean setEmaneConfig(CoreNode node, List options) throws IOException { - String url = getUrl(String.format("sessions/%s/emane/config", sessionId)); - SetEmaneConfig setEmaneConfig = new SetEmaneConfig(); - setEmaneConfig.setNode(node.getId()); - setEmaneConfig.setValues(options); - return WebUtils.putJson(url, setEmaneConfig); - } - - @Override - public boolean setEmaneModelConfig(Integer id, String model, List options) throws IOException { - String url = getUrl(String.format("sessions/%s/emane/model/config", sessionId)); - SetEmaneModelConfig setEmaneModelConfig = new SetEmaneModelConfig(); - setEmaneModelConfig.setNode(id); - setEmaneModelConfig.setName(model); - setEmaneModelConfig.setValues(options); - return WebUtils.putJson(url, setEmaneModelConfig); - } - - @Override - public boolean isRunning() { - return sessionState == SessionState.RUNTIME; - } - - @Override - public void saveSession(File file) throws IOException { - String path = String.format("sessions/%s/xml", sessionId); - String url = getUrl(path); - WebUtils.getFile(url, file); - } - - @Override - public SessionOverview openSession(File file) throws IOException { - String url = getUrl("sessions/xml"); - return WebUtils.postFile(url, file, SessionOverview.class); - } - - @Override - public List getSessionConfig() throws IOException { - String url = getUrl(String.format("sessions/%s/options", sessionId)); - GetConfig getConfig = WebUtils.getJson(url, GetConfig.class); - return getConfig.getGroups(); - } - - @Override - public boolean setSessionConfig(List configOptions) throws IOException { - String url = getUrl(String.format("sessions/%s/options", sessionId)); - SetConfig setConfig = new SetConfig(configOptions); - return WebUtils.putJson(url, setConfig); - } - - @Override - public LocationConfig getLocationConfig() throws IOException { - String url = getUrl(String.format("sessions/%s/location", sessionId)); - return WebUtils.getJson(url, LocationConfig.class); - } - - @Override - public boolean setLocationConfig(LocationConfig config) throws IOException { - String url = getUrl(String.format("sessions/%s/location", sessionId)); - return WebUtils.putJson(url, config); - } - - @Override - public String nodeCommand(CoreNode node, String command) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/command", sessionId, node.getId())); - return WebUtils.putJson(url, command, String.class); - } - - @Override - public boolean createNode(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes", sessionId)); - return WebUtils.postJson(url, node); - } - - - @Override - public boolean editNode(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s", sessionId, node.getId())); - return WebUtils.putJson(url, node); - } - - @Override - public boolean deleteNode(CoreNode node) throws IOException { - String url = getUrl(String.format("/sessions/%s/nodes/%s", sessionId, node.getId())); - return WebUtils.delete(url); - } - - @Override - public boolean createLink(CoreLink link) throws IOException { - String url = getUrl(String.format("sessions/%s/links", sessionId)); - return WebUtils.postJson(url, link); - } - - @Override - public boolean editLink(CoreLink link) throws IOException { - String url = getUrl(String.format("sessions/%s/links", sessionId)); - return WebUtils.putJson(url, link); - } - - @Override - public boolean createHook(Hook hook) throws IOException { - String url = getUrl(String.format("sessions/%s/hooks", sessionId)); - return WebUtils.postJson(url, hook); - } - - @Override - public List getHooks() throws IOException { - String url = getUrl(String.format("sessions/%s/hooks", sessionId)); - GetHooks getHooks = WebUtils.getJson(url, GetHooks.class); - return getHooks.getHooks(); - } - - @Override - public WlanConfig getWlanConfig(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/wlan", sessionId, node.getId())); - return WebUtils.getJson(url, WlanConfig.class); - } - - @Override - public boolean setWlanConfig(CoreNode node, WlanConfig config) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/wlan", sessionId, node.getId())); - return WebUtils.putJson(url, config); - } - - @Override - public String getTerminalCommand(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/terminal", sessionId, node.getId())); - return WebUtils.getJson(url, String.class); - } - - @Override - public boolean setMobilityConfig(CoreNode node, MobilityConfig config) throws IOException { - boolean uploaded = uploadFile(config.getScriptFile()); - if (!uploaded) { - throw new IOException("failed to upload mobility script"); - } - - String url = getUrl(String.format("sessions/%s/nodes/%s/mobility", sessionId, node.getId())); - config.setFile(config.getScriptFile().getName()); - return WebUtils.postJson(url, config); - } - - @Override - public Map getMobilityConfigs() throws IOException { - String url = getUrl(String.format("sessions/%s/mobility/configs", sessionId)); - GetMobilityConfigs getMobilityConfigs = WebUtils.getJson(url, GetMobilityConfigs.class); - return getMobilityConfigs.getConfigurations(); - } - - @Override - public MobilityConfig getMobilityConfig(CoreNode node) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/mobility", sessionId, node.getId())); - return WebUtils.getJson(url, MobilityConfig.class); - } - - @Override - public boolean mobilityAction(CoreNode node, String action) throws IOException { - String url = getUrl(String.format("sessions/%s/nodes/%s/mobility/%s", sessionId, node.getId(), action)); - return WebUtils.putJson(url); - } -} diff --git a/corefx/src/main/java/com/core/client/rest/GetConfig.java b/corefx/src/main/java/com/core/client/rest/GetConfig.java deleted file mode 100644 index 61a843b6..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.client.rest; - -import com.core.data.ConfigGroup; -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class GetConfig { - private List groups = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/GetDefaultServices.java b/corefx/src/main/java/com/core/client/rest/GetDefaultServices.java deleted file mode 100644 index b134cbc0..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetDefaultServices.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.core.client.rest; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class GetDefaultServices { - private Map> defaults = new HashMap<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/GetEmaneModels.java b/corefx/src/main/java/com/core/client/rest/GetEmaneModels.java deleted file mode 100644 index 43cef1c6..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetEmaneModels.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.core.client.rest; - -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class GetEmaneModels { - private List models = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/GetHooks.java b/corefx/src/main/java/com/core/client/rest/GetHooks.java deleted file mode 100644 index fe26e828..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetHooks.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.client.rest; - -import com.core.data.Hook; -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class GetHooks { - private List hooks = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/GetMobilityConfigs.java b/corefx/src/main/java/com/core/client/rest/GetMobilityConfigs.java deleted file mode 100644 index e5905b7e..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetMobilityConfigs.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.client.rest; - -import com.core.data.MobilityConfig; -import lombok.Data; - -import java.util.HashMap; -import java.util.Map; - -@Data -public class GetMobilityConfigs { - private Map configurations = new HashMap<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/GetServices.java b/corefx/src/main/java/com/core/client/rest/GetServices.java deleted file mode 100644 index 17e04ddc..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetServices.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.core.client.rest; - -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Map; - -@Data -@NoArgsConstructor -public class GetServices { - private Map> groups; -} diff --git a/corefx/src/main/java/com/core/client/rest/GetSessions.java b/corefx/src/main/java/com/core/client/rest/GetSessions.java deleted file mode 100644 index 674fc83a..00000000 --- a/corefx/src/main/java/com/core/client/rest/GetSessions.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.core.client.rest; - -import com.core.data.SessionOverview; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; - -@Data -@NoArgsConstructor -public class GetSessions { - private List sessions = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/ServiceFile.java b/corefx/src/main/java/com/core/client/rest/ServiceFile.java deleted file mode 100644 index 977ed984..00000000 --- a/corefx/src/main/java/com/core/client/rest/ServiceFile.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.core.client.rest; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class ServiceFile { - private String name; - private String data; -} diff --git a/corefx/src/main/java/com/core/client/rest/SetConfig.java b/corefx/src/main/java/com/core/client/rest/SetConfig.java deleted file mode 100644 index 0d3f11ea..00000000 --- a/corefx/src/main/java/com/core/client/rest/SetConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.core.client.rest; - -import com.core.data.ConfigOption; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SetConfig { - private List values = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/SetEmaneConfig.java b/corefx/src/main/java/com/core/client/rest/SetEmaneConfig.java deleted file mode 100644 index ee947c51..00000000 --- a/corefx/src/main/java/com/core/client/rest/SetEmaneConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.core.client.rest; - -import com.core.data.ConfigOption; -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class SetEmaneConfig { - private Integer node; - private List values = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/SetEmaneModelConfig.java b/corefx/src/main/java/com/core/client/rest/SetEmaneModelConfig.java deleted file mode 100644 index e5c37092..00000000 --- a/corefx/src/main/java/com/core/client/rest/SetEmaneModelConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.core.client.rest; - -import com.core.data.ConfigOption; -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class SetEmaneModelConfig { - private Integer node; - private String name; - private List values = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/client/rest/WlanConfig.java b/corefx/src/main/java/com/core/client/rest/WlanConfig.java deleted file mode 100644 index 45b9805f..00000000 --- a/corefx/src/main/java/com/core/client/rest/WlanConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.client.rest; - -import lombok.Data; - -@Data -public class WlanConfig { - private String range; - private String bandwidth; - private String jitter; - private String delay; - private String error; -} diff --git a/corefx/src/main/java/com/core/data/BridgeThroughput.java b/corefx/src/main/java/com/core/data/BridgeThroughput.java deleted file mode 100644 index 167fb402..00000000 --- a/corefx/src/main/java/com/core/data/BridgeThroughput.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.core.data; - -import lombok.Data; - -@Data -public class BridgeThroughput { - private int node; - private Double throughput; -} diff --git a/corefx/src/main/java/com/core/data/ConfigDataType.java b/corefx/src/main/java/com/core/data/ConfigDataType.java deleted file mode 100644 index 3dd44864..00000000 --- a/corefx/src/main/java/com/core/data/ConfigDataType.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.core.data; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public enum ConfigDataType { - UINT8(1), - UINT16(2), - UINT32(3), - UINT64(4), - INT8(5), - INT16(6), - INT32(7), - INT64(8), - FLOAT(9), - STRING(10), - BOOL(11); - - private static final Map LOOKUP = new HashMap<>(); - - static { - Arrays.stream(ConfigDataType.values()).forEach(x -> LOOKUP.put(x.getValue(), x)); - } - - private final int value; - - ConfigDataType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - - public static ConfigDataType get(int value) { - return LOOKUP.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/ConfigGroup.java b/corefx/src/main/java/com/core/data/ConfigGroup.java deleted file mode 100644 index 9b45bdb7..00000000 --- a/corefx/src/main/java/com/core/data/ConfigGroup.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.data; - -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class ConfigGroup { - private String name; - private List options = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/data/ConfigOption.java b/corefx/src/main/java/com/core/data/ConfigOption.java deleted file mode 100644 index 77af265e..00000000 --- a/corefx/src/main/java/com/core/data/ConfigOption.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.core.data; - -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class ConfigOption { - private String label; - private String name; - private String value; - private Integer type; - private List select = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/data/CoreEvent.java b/corefx/src/main/java/com/core/data/CoreEvent.java deleted file mode 100644 index 9ac8ed03..00000000 --- a/corefx/src/main/java/com/core/data/CoreEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonSetter; -import lombok.Data; - -@Data -public class CoreEvent { - private Integer session; - private Integer node; - private String name; - private Double time; - private EventType eventType; - private String data; - - @JsonSetter("event_type") - public void setEventType(int value) { - eventType = EventType.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/CoreInterface.java b/corefx/src/main/java/com/core/data/CoreInterface.java deleted file mode 100644 index f159f10e..00000000 --- a/corefx/src/main/java/com/core/data/CoreInterface.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class CoreInterface { - private Integer id; - private String name; - private String mac; - private String ip4; - @JsonProperty("ip4mask") - private Integer ip4Mask; - private String ip6; - @JsonProperty("ip6mask") - private String ip6Mask; -} diff --git a/corefx/src/main/java/com/core/data/CoreLink.java b/corefx/src/main/java/com/core/data/CoreLink.java deleted file mode 100644 index f3d4a215..00000000 --- a/corefx/src/main/java/com/core/data/CoreLink.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public class CoreLink { - @EqualsAndHashCode.Include - private Integer id; - - @JsonIgnore - private Float weight = 1.0f; - - @JsonIgnore - private boolean loaded = true; - - @JsonIgnore - private double throughput; - - @JsonIgnore - private boolean visible = true; - - @JsonProperty("message_type") - private Integer messageType; - - private Integer type = 1; - - @JsonProperty("node_one") - private Integer nodeOne; - - @JsonProperty("node_two") - private Integer nodeTwo; - - @JsonProperty("interface_one") - private CoreInterface interfaceOne; - - @JsonProperty("interface_two") - private CoreInterface interfaceTwo; - - private CoreLinkOptions options = new CoreLinkOptions(); - - public CoreLink(Integer id) { - this.id = id; - this.weight = (float) id; - this.loaded = false; - } - - public boolean isWireless() { - return interfaceOne == null && interfaceTwo == null; - } -} diff --git a/corefx/src/main/java/com/core/data/CoreLinkOptions.java b/corefx/src/main/java/com/core/data/CoreLinkOptions.java deleted file mode 100644 index 6556d3c0..00000000 --- a/corefx/src/main/java/com/core/data/CoreLinkOptions.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.core.data; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class CoreLinkOptions { - private String opaque; - private Integer session; - private Double jitter; - private Integer key; - private Double mburst; - private Double mer; - private Double per; - private Double bandwidth; - private Double burst; - private Double delay; - private Double dup; - private Integer unidirectional; -} diff --git a/corefx/src/main/java/com/core/data/CoreNode.java b/corefx/src/main/java/com/core/data/CoreNode.java deleted file mode 100644 index f441bd69..00000000 --- a/corefx/src/main/java/com/core/data/CoreNode.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.core.data; - -import com.core.graph.RadioIcon; -import com.core.utils.IconUtils; -import com.fasterxml.jackson.annotation.JsonIgnore; -import edu.uci.ics.jung.visualization.LayeredIcon; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.HashSet; -import java.util.Set; - -@Data -@NoArgsConstructor -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public class CoreNode { - private static final Logger logger = LogManager.getLogger(); - @EqualsAndHashCode.Include - private Integer id; - private String name; - private Integer type; - private String model; - private Position position = new Position(); - private Set services = new HashSet<>(); - private String emane; - private String url; - @JsonIgnore - private NodeType nodeType; - @JsonIgnore - private String icon; - @JsonIgnore - private boolean loaded = true; - @JsonIgnore - private LayeredIcon graphIcon; - @JsonIgnore - private RadioIcon radioIcon = new RadioIcon(); - - public CoreNode(Integer id) { - this.id = id; - this.name = String.format("Node%s", this.id); - this.loaded = false; - } - - public void setNodeType(NodeType nodeType) { - type = nodeType.getValue(); - model = nodeType.getModel(); - icon = nodeType.getIcon(); - if (icon.startsWith("file:")) { - graphIcon = IconUtils.getExternalLayeredIcon(icon); - } else { - graphIcon = IconUtils.getLayeredIcon(icon); - } - graphIcon.add(radioIcon); - this.nodeType = nodeType; - } -} diff --git a/corefx/src/main/java/com/core/data/CoreService.java b/corefx/src/main/java/com/core/data/CoreService.java deleted file mode 100644 index ed9dd230..00000000 --- a/corefx/src/main/java/com/core/data/CoreService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class CoreService { - private List executables = new ArrayList<>(); - private List dependencies = new ArrayList<>(); - private List dirs = new ArrayList<>(); - private List configs = new ArrayList<>(); - private List startup = new ArrayList<>(); - private List validate = new ArrayList<>(); - @JsonProperty("validation_mode") - private String validationMode; - @JsonProperty("validation_timer") - private String validationTimer; - private List shutdown = new ArrayList<>(); - private String meta; -} diff --git a/corefx/src/main/java/com/core/data/EventType.java b/corefx/src/main/java/com/core/data/EventType.java deleted file mode 100644 index 487de4c1..00000000 --- a/corefx/src/main/java/com/core/data/EventType.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.core.data; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public enum EventType { - NONE(0), - DEFINITION_STATE(1), - CONFIGURATION_STATE(2), - INSTANTIATION_STATE(3), - RUNTIME_STATE(4), - DATACOLLECT_STATE(5), - SHUTDOWN_STATE(6), - START(7), - STOP(8), - PAUSE(9), - RESTART(10), - FILE_OPEN(11), - FILE_SAVE(12), - SCHEDULED(13), - RECONFIGURE(14), - INSTANTIATION_COMPLETE(15); - - private static final Map LOOKUP = new HashMap<>(); - - static { - Arrays.stream(EventType.values()).forEach(x -> LOOKUP.put(x.getValue(), x)); - } - - private final int value; - - EventType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - - public static EventType get(int value) { - return LOOKUP.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/Hook.java b/corefx/src/main/java/com/core/data/Hook.java deleted file mode 100644 index 35b1a934..00000000 --- a/corefx/src/main/java/com/core/data/Hook.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Data; - -@Data -public class Hook { - private String file; - private Integer state; - @JsonIgnore - private String stateDisplay; - private String data; -} diff --git a/corefx/src/main/java/com/core/data/InterfaceThroughput.java b/corefx/src/main/java/com/core/data/InterfaceThroughput.java deleted file mode 100644 index 1c6303e0..00000000 --- a/corefx/src/main/java/com/core/data/InterfaceThroughput.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -@Data -public class InterfaceThroughput { - private int node; - @JsonProperty("interface") - private int nodeInterface; - private double throughput; -} diff --git a/corefx/src/main/java/com/core/data/LinkTypes.java b/corefx/src/main/java/com/core/data/LinkTypes.java deleted file mode 100644 index 4bfaf1dc..00000000 --- a/corefx/src/main/java/com/core/data/LinkTypes.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.core.data; - -import java.util.HashMap; -import java.util.Map; - -public enum LinkTypes { - WIRELESS(0), - WIRED(1); - - private static final Map LOOKUP = new HashMap<>(); - - static { - for (LinkTypes state : LinkTypes.values()) { - LOOKUP.put(state.getValue(), state); - } - } - - private final int value; - - LinkTypes(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - public static LinkTypes get(int value) { - return LOOKUP.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/Location.java b/corefx/src/main/java/com/core/data/Location.java deleted file mode 100644 index f5c399c4..00000000 --- a/corefx/src/main/java/com/core/data/Location.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.core.data; - -import lombok.Data; - -@Data -public class Location { - private Double latitude = 0.0; - private Double longitude = 0.0; - private Double altitude = 0.0; -} diff --git a/corefx/src/main/java/com/core/data/LocationConfig.java b/corefx/src/main/java/com/core/data/LocationConfig.java deleted file mode 100644 index 10ba11ac..00000000 --- a/corefx/src/main/java/com/core/data/LocationConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.core.data; - -import lombok.Data; - -@Data -public class LocationConfig { - private Position position = new Position(); - private Location location = new Location(); - private Double scale; -} diff --git a/corefx/src/main/java/com/core/data/MessageFlags.java b/corefx/src/main/java/com/core/data/MessageFlags.java deleted file mode 100644 index 6272099b..00000000 --- a/corefx/src/main/java/com/core/data/MessageFlags.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.core.data; - -import java.util.HashMap; -import java.util.Map; - -public enum MessageFlags { - ADD(1), - DELETE(2), - CRI(4), - LOCAL(8), - STRING(16), - TEXT(32), - TTY(64); - - private static final Map LOOKUP = new HashMap<>(); - - static { - for (MessageFlags state : MessageFlags.values()) { - LOOKUP.put(state.getValue(), state); - } - } - - private final int value; - - MessageFlags(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - public static MessageFlags get(int value) { - return LOOKUP.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/MobilityConfig.java b/corefx/src/main/java/com/core/data/MobilityConfig.java deleted file mode 100644 index 67b5d769..00000000 --- a/corefx/src/main/java/com/core/data/MobilityConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.core.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.io.File; - -@Data -public class MobilityConfig { - private String file; - @JsonIgnore - private File scriptFile; - @JsonProperty("refresh_ms") - private Integer refresh; - private String loop; - private String autostart; - private String map; - @JsonProperty("script_start") - private String startScript; - @JsonProperty("script_pause") - private String pauseScript; - @JsonProperty("script_stop") - private String stopScript; -} diff --git a/corefx/src/main/java/com/core/data/NodeType.java b/corefx/src/main/java/com/core/data/NodeType.java deleted file mode 100644 index 4af7dc3d..00000000 --- a/corefx/src/main/java/com/core/data/NodeType.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.core.data; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -@Data -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public class NodeType { - private static final Logger logger = LogManager.getLogger(); - private static final AtomicInteger idGenerator = new AtomicInteger(0); - private static final Map ID_LOOKUP = new HashMap<>(); - public static final int DEFAULT = 0; - public static final int SWITCH = 4; - public static final int HUB = 5; - public static final int WLAN = 6; - public static final int EMANE = 10; - @EqualsAndHashCode.Include - private final int id; - private final int value; - private final Set services = new TreeSet<>(); - private String display; - private String model; - private String icon; - - // PHYSICAL = 1 -// RJ45 = 7 -// TUNNEL = 8 -// KTUNNEL = 9 -// EMANE = 10 -// TAP_BRIDGE = 11 -// PEER_TO_PEER = 12 -// CONTROL_NET = 13 -// EMANE_NET = 14; - - static { - add(new NodeType(SWITCH, "lanswitch", "Switch", "/icons/switch-100.png")); - add(new NodeType(HUB, "hub", "Hub", "/icons/hub-100.png")); - add(new NodeType(WLAN, "wlan", "WLAN", "/icons/wlan-100.png")); - add(new NodeType(EMANE, "wlan", "EMANE", "/icons/emane-100.png")); - } - - - public NodeType(int value, String model, String display, String icon) { - this.id = idGenerator.incrementAndGet(); - this.value = value; - this.model = model; - this.display = display; - this.icon = icon; - } - - public static void add(NodeType nodeType) { - ID_LOOKUP.put(nodeType.getId(), nodeType); - } - - public static void remove(NodeType nodeType) { - ID_LOOKUP.remove(nodeType.getId()); - } - - public static NodeType get(Integer id) { - return ID_LOOKUP.get(id); - } - - public static Collection getAll() { - return ID_LOOKUP.values(); - } - - public static NodeType find(Integer type, String model) { - return ID_LOOKUP.values().stream() - .filter(nodeType -> { - boolean sameType = nodeType.getValue() == type; - boolean sameModel; - if (model != null) { - sameModel = model.equals(nodeType.getModel()); - } else { - sameModel = nodeType.getModel() == null; - } - return sameType && sameModel; - }) - .findFirst().orElse(null); - } -} diff --git a/corefx/src/main/java/com/core/data/Position.java b/corefx/src/main/java/com/core/data/Position.java deleted file mode 100644 index c5bfa728..00000000 --- a/corefx/src/main/java/com/core/data/Position.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.data; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class Position { - private Double x; - private Double y; - private Double z; -} diff --git a/corefx/src/main/java/com/core/data/Session.java b/corefx/src/main/java/com/core/data/Session.java deleted file mode 100644 index 374e379d..00000000 --- a/corefx/src/main/java/com/core/data/Session.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.core.data; - -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; - -@Data -@NoArgsConstructor -public class Session { - private Integer state; - private List nodes = new ArrayList<>(); - private List links = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/data/SessionOverview.java b/corefx/src/main/java/com/core/data/SessionOverview.java deleted file mode 100644 index 47773338..00000000 --- a/corefx/src/main/java/com/core/data/SessionOverview.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.core.data; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class SessionOverview { - private Integer id; - private Integer state; - private Integer nodes = 0; - private String url; -} diff --git a/corefx/src/main/java/com/core/data/SessionState.java b/corefx/src/main/java/com/core/data/SessionState.java deleted file mode 100644 index c9e92904..00000000 --- a/corefx/src/main/java/com/core/data/SessionState.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.core.data; - -import java.util.HashMap; -import java.util.Map; - -public enum SessionState { - DEFINITION(1), - CONFIGURATION(2), - INSTANTIATION(3), - RUNTIME(4), - DATA_COLLECT(5), - SHUTDOWN(6), - START(7), - STOP(8), - PAUSE(9); - - private static final Map LOOKUP = new HashMap<>(); - - static { - for (SessionState state : SessionState.values()) { - LOOKUP.put(state.getValue(), state); - } - } - - private final int value; - - SessionState(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - public static SessionState get(int value) { - return LOOKUP.get(value); - } -} diff --git a/corefx/src/main/java/com/core/data/Throughputs.java b/corefx/src/main/java/com/core/data/Throughputs.java deleted file mode 100644 index c02a7f6f..00000000 --- a/corefx/src/main/java/com/core/data/Throughputs.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.core.data; - -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class Throughputs { - private List interfaces = new ArrayList<>(); - private List bridges = new ArrayList<>(); -} diff --git a/corefx/src/main/java/com/core/datavis/CoreGraph.java b/corefx/src/main/java/com/core/datavis/CoreGraph.java deleted file mode 100644 index f5a0c0fd..00000000 --- a/corefx/src/main/java/com/core/datavis/CoreGraph.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.core.datavis; - -import lombok.Data; - -@Data -public class CoreGraph { - private String title; - private CoreGraphAxis xAxis; - private CoreGraphAxis yAxis; - private GraphType graphType; -} diff --git a/corefx/src/main/java/com/core/datavis/CoreGraphAxis.java b/corefx/src/main/java/com/core/datavis/CoreGraphAxis.java deleted file mode 100644 index 8631f3a1..00000000 --- a/corefx/src/main/java/com/core/datavis/CoreGraphAxis.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.core.datavis; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CoreGraphAxis { - private String label; - private Double lower; - private Double upper; - private Double tick; -} diff --git a/corefx/src/main/java/com/core/datavis/CoreGraphData.java b/corefx/src/main/java/com/core/datavis/CoreGraphData.java deleted file mode 100644 index ff0d4c77..00000000 --- a/corefx/src/main/java/com/core/datavis/CoreGraphData.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.core.datavis; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CoreGraphData { - private String name; - private Double x; - private Double y; - private Double weight; -} diff --git a/corefx/src/main/java/com/core/datavis/CoreGraphWrapper.java b/corefx/src/main/java/com/core/datavis/CoreGraphWrapper.java deleted file mode 100644 index eae92e8f..00000000 --- a/corefx/src/main/java/com/core/datavis/CoreGraphWrapper.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.core.datavis; - -import javafx.scene.chart.*; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -public class CoreGraphWrapper { - private static final Logger logger = LogManager.getLogger(); - private final GraphType graphType; - private PieChart pieChart; - private final Map pieData = new HashMap<>(); - private BarChart barChart; - private final Map> barMap = new HashMap<>(); - private XYChart xyChart; - private final XYChart.Series series = new XYChart.Series<>(); - private final XYChart.Series barSeries = new XYChart.Series<>(); - private AtomicInteger timeValue = new AtomicInteger(0); - - public CoreGraphWrapper(CoreGraph coreGraph) { - graphType = coreGraph.getGraphType(); - createChart(coreGraph); - } - - public Chart getChart() { - switch (graphType) { - case PIE: - return pieChart; - case BAR: - return barChart; - default: - return xyChart; - } - } - - public void add(CoreGraphData coreGraphData) { - switch (graphType) { - case PIE: - case BAR: - add(coreGraphData.getName(), coreGraphData.getY()); - break; - case TIME: - add(coreGraphData.getY()); - break; - case BUBBLE: - add(coreGraphData.getX(), coreGraphData.getY(), coreGraphData.getWeight()); - break; - default: - add(coreGraphData.getX(), coreGraphData.getY()); - } - } - - public void add(String name, double value) { - if (GraphType.PIE == graphType) { - PieChart.Data data = pieData.computeIfAbsent(name, x -> { - PieChart.Data newData = new PieChart.Data(x, value); - pieChart.getData().add(newData); - return newData; - }); - data.setPieValue(value); - } else { - XYChart.Data data = barMap.computeIfAbsent(name, x -> { - XYChart.Data newData = new XYChart.Data<>(name, value); - barSeries.getData().add(newData); - return newData; - }); - data.setYValue(value); - } - } - - public void add(Number y) { - series.getData().add(new XYChart.Data<>(timeValue.getAndIncrement(), y)); - } - - public void add(Number x, Number y) { - series.getData().add(new XYChart.Data<>(x, y)); - } - - public void add(Number x, Number y, Number weight) { - series.getData().add(new XYChart.Data<>(x, y, weight)); - } - - private NumberAxis getAxis(CoreGraphAxis graphAxis) { - return new NumberAxis(graphAxis.getLabel(), graphAxis.getLower(), - graphAxis.getUpper(), graphAxis.getTick()); - } - - private void createChart(CoreGraph coreGraph) { - NumberAxis xAxis; - NumberAxis yAxis; - - switch (coreGraph.getGraphType()) { - case AREA: - xAxis = getAxis(coreGraph.getXAxis()); - yAxis = getAxis(coreGraph.getYAxis()); - xyChart = new AreaChart<>(xAxis, yAxis); - xyChart.setTitle(coreGraph.getTitle()); - xyChart.setLegendVisible(false); - xyChart.getData().add(series); - break; - case TIME: - xAxis = new NumberAxis(); - xAxis.setLabel(coreGraph.getXAxis().getLabel()); - xAxis.setTickUnit(1); - xAxis.setLowerBound(0); - yAxis = getAxis(coreGraph.getYAxis()); - xyChart = new LineChart<>(xAxis, yAxis); - xyChart.setTitle(coreGraph.getTitle()); - xyChart.setLegendVisible(false); - xyChart.getData().add(series); - break; - case LINE: - xAxis = getAxis(coreGraph.getXAxis()); - yAxis = getAxis(coreGraph.getYAxis()); - xyChart = new LineChart<>(xAxis, yAxis); - xyChart.setTitle(coreGraph.getTitle()); - xyChart.setLegendVisible(false); - xyChart.getData().add(series); - break; - case BUBBLE: - xAxis = getAxis(coreGraph.getXAxis()); - yAxis = getAxis(coreGraph.getYAxis()); - xyChart = new BubbleChart<>(xAxis, yAxis); - xyChart.setTitle(coreGraph.getTitle()); - xyChart.setLegendVisible(false); - xyChart.getData().add(series); - break; - case SCATTER: - xAxis = getAxis(coreGraph.getXAxis()); - yAxis = getAxis(coreGraph.getYAxis()); - xyChart = new ScatterChart<>(xAxis, yAxis); - xyChart.setTitle(coreGraph.getTitle()); - xyChart.setLegendVisible(false); - xyChart.getData().add(series); - break; - case PIE: - pieChart = new PieChart(); - pieChart.setTitle(coreGraph.getTitle()); - break; - case BAR: - CategoryAxis categoryAxis = new CategoryAxis(); - categoryAxis.setLabel(coreGraph.getXAxis().getLabel()); - yAxis = getAxis(coreGraph.getYAxis()); - barChart = new BarChart<>(categoryAxis, yAxis); - barChart.setLegendVisible(false); - barChart.setTitle(coreGraph.getTitle()); - barChart.getData().add(barSeries); - break; - default: - throw new IllegalArgumentException(String.format("unknown graph type: %s", - coreGraph.getGraphType())); - } - } -} diff --git a/corefx/src/main/java/com/core/datavis/GraphType.java b/corefx/src/main/java/com/core/datavis/GraphType.java deleted file mode 100644 index 7609eee3..00000000 --- a/corefx/src/main/java/com/core/datavis/GraphType.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.core.datavis; - -public enum GraphType { - PIE, - LINE, - TIME, - AREA, - BAR, - SCATTER, - BUBBLE -} diff --git a/corefx/src/main/java/com/core/graph/AbstractNodeContextMenu.java b/corefx/src/main/java/com/core/graph/AbstractNodeContextMenu.java deleted file mode 100644 index d04097c2..00000000 --- a/corefx/src/main/java/com/core/graph/AbstractNodeContextMenu.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreNode; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.control.MenuItem; - -abstract class AbstractNodeContextMenu extends GraphContextMenu { - final CoreNode coreNode; - - AbstractNodeContextMenu(Controller controller, CoreNode coreNode) { - super(controller); - this.coreNode = coreNode; - } - - void addMenuItem(String text, EventHandler handler) { - MenuItem menuItem = new MenuItem(text); - menuItem.setOnAction(handler); - getItems().add(menuItem); - } -} diff --git a/corefx/src/main/java/com/core/graph/BackgroundPaintable.java b/corefx/src/main/java/com/core/graph/BackgroundPaintable.java deleted file mode 100644 index b0cfe6a3..00000000 --- a/corefx/src/main/java/com/core/graph/BackgroundPaintable.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.core.graph; - -import edu.uci.ics.jung.visualization.Layer; -import edu.uci.ics.jung.visualization.VisualizationViewer; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.geom.AffineTransform; -import java.io.IOException; -import java.nio.file.Paths; - -public class BackgroundPaintable implements VisualizationViewer.Paintable { - private final ImageIcon imageIcon; - private final VisualizationViewer vv; - private final String imagePath; - - public BackgroundPaintable(String imagePath, VisualizationViewer vv) throws IOException { - this.imagePath = imagePath; - Image image = ImageIO.read(Paths.get(imagePath).toFile()); - imageIcon = new ImageIcon(image); - this.vv = vv; - } - - public String getImage() { - return imagePath; - } - - @Override - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - AffineTransform oldXform = g2d.getTransform(); - AffineTransform lat = - vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getTransform(); - AffineTransform vat = - vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getTransform(); - AffineTransform at = new AffineTransform(); - at.concatenate(g2d.getTransform()); - at.concatenate(vat); - at.concatenate(lat); - g2d.setTransform(at); - g.drawImage(imageIcon.getImage(), 0, 0, - imageIcon.getIconWidth(), imageIcon.getIconHeight(), vv); - g2d.setTransform(oldXform); - } - - @Override - public boolean useTransform() { - return false; - } -} diff --git a/corefx/src/main/java/com/core/graph/CoreAddresses.java b/corefx/src/main/java/com/core/graph/CoreAddresses.java deleted file mode 100644 index 5db724b6..00000000 --- a/corefx/src/main/java/com/core/graph/CoreAddresses.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.core.graph; - -import com.core.data.CoreInterface; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Collection; - -public class CoreAddresses { - private static final Logger logger = LogManager.getLogger(); - public static final int IP4_MASK = 24; - public static final int IP4_INDEX = (IP4_MASK / 8) - 1; - - private String ip4Base; - - public CoreAddresses(String ip4Base) { - this.ip4Base = ip4Base; - } - - public int getSubnet(Collection nodeOneInterfaces, Collection nodeTwoInterfaces) { - int subOne = getMaxSubnet(nodeOneInterfaces); - int subTwo = getMaxSubnet(nodeTwoInterfaces); - logger.info("next subnet: {} - {}", subOne, subTwo); - return Math.max(subOne, subTwo) + 1; - } - - private int getMaxSubnet(Collection coreInterfaces) { - int sub = 0; - for (CoreInterface coreInterface : coreInterfaces) { - String[] values = coreInterface.getIp4().split("\\."); - int currentSub = Integer.parseInt(values[IP4_INDEX]); - logger.info("checking {} value {}", coreInterface.getIp4(), currentSub); - sub = Math.max(currentSub, sub); - } - return sub; - } - - public String getIp4Address(int sub, int id) { - return String.format("%s.%s.%s", ip4Base, sub, id); - } -} diff --git a/corefx/src/main/java/com/core/graph/CoreAnnotatingGraphMousePlugin.java b/corefx/src/main/java/com/core/graph/CoreAnnotatingGraphMousePlugin.java deleted file mode 100644 index 6cbd1bf8..00000000 --- a/corefx/src/main/java/com/core/graph/CoreAnnotatingGraphMousePlugin.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import edu.uci.ics.jung.visualization.RenderContext; -import edu.uci.ics.jung.visualization.VisualizationViewer; -import edu.uci.ics.jung.visualization.annotations.AnnotatingGraphMousePlugin; -import edu.uci.ics.jung.visualization.annotations.Annotation; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.geom.Point2D; -import java.awt.geom.RectangularShape; - -public class CoreAnnotatingGraphMousePlugin extends AnnotatingGraphMousePlugin { - private static final Logger logger = LogManager.getLogger(); - private final Controller controller; - private JFrame frame = new JFrame(); - - public CoreAnnotatingGraphMousePlugin(Controller controller, RenderContext renderContext) { - super(renderContext); - this.controller = controller; - frame.setVisible(false); - frame.setAlwaysOnTop(true); - } - - @Override - public void mouseReleased(MouseEvent e) { - VisualizationViewer vv = (VisualizationViewer) e.getSource(); - if (e.isPopupTrigger()) { - frame.setLocationRelativeTo(vv); - String annotationString = JOptionPane.showInputDialog(frame, "Annotation:", - "Annotation Label", JOptionPane.PLAIN_MESSAGE); - if (annotationString != null && annotationString.length() > 0) { - Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(this.down); - Annotation annotation = new Annotation(annotationString, this.layer, - this.annotationColor, this.fill, p); - this.annotationManager.add(this.layer, annotation); - } - } else if (e.getModifiers() == this.modifiers && this.down != null) { - Point2D out = e.getPoint(); - RectangularShape arect = (RectangularShape) this.rectangularShape.clone(); - arect.setFrameFromDiagonal(this.down, out); - Shape s = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(arect); - Annotation annotation = new Annotation(s, this.layer, this.annotationColor, this.fill, out); - this.annotationManager.add(this.layer, annotation); - } - - this.down = null; - vv.removePostRenderPaintable(this.lensPaintable); - vv.repaint(); - } - - -} diff --git a/corefx/src/main/java/com/core/graph/CoreEditingModalGraphMouse.java b/corefx/src/main/java/com/core/graph/CoreEditingModalGraphMouse.java deleted file mode 100644 index 9d80183e..00000000 --- a/corefx/src/main/java/com/core/graph/CoreEditingModalGraphMouse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.google.common.base.Supplier; -import edu.uci.ics.jung.visualization.RenderContext; -import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse; - -public class CoreEditingModalGraphMouse extends EditingModalGraphMouse { - public CoreEditingModalGraphMouse(Controller controller, NetworkGraph networkGraph, - RenderContext rc, Supplier vertexFactory, Supplier edgeFactory) { - super(rc, vertexFactory, edgeFactory); - remove(annotatingPlugin); - remove(popupEditingPlugin); - annotatingPlugin = new CoreAnnotatingGraphMousePlugin<>(controller, rc); - popupEditingPlugin = new CorePopupGraphMousePlugin<>(controller, networkGraph, vertexFactory, edgeFactory); - } -} diff --git a/corefx/src/main/java/com/core/graph/CoreObservableGraph.java b/corefx/src/main/java/com/core/graph/CoreObservableGraph.java deleted file mode 100644 index cbf678f0..00000000 --- a/corefx/src/main/java/com/core/graph/CoreObservableGraph.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.core.graph; - -import edu.uci.ics.jung.graph.Graph; -import edu.uci.ics.jung.graph.ObservableGraph; -import edu.uci.ics.jung.graph.util.EdgeType; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class CoreObservableGraph extends ObservableGraph { - private static final Logger logger = LogManager.getLogger(); - - public CoreObservableGraph(Graph graph) { - super(graph); - } - - @Override - public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { - if (v1 == null || v2 == null) { - return false; - } - return super.addEdge(e, v1, v2, edgeType); - } - - @Override - public boolean addEdge(E e, V v1, V v2) { - if (v1 == null || v2 == null) { - return false; - } - return super.addEdge(e, v1, v2); - } -} diff --git a/corefx/src/main/java/com/core/graph/CorePopupGraphMousePlugin.java b/corefx/src/main/java/com/core/graph/CorePopupGraphMousePlugin.java deleted file mode 100644 index 3b96c9fa..00000000 --- a/corefx/src/main/java/com/core/graph/CorePopupGraphMousePlugin.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreLink; -import com.core.data.CoreNode; -import com.core.data.NodeType; -import com.google.common.base.Supplier; -import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; -import edu.uci.ics.jung.algorithms.layout.Layout; -import edu.uci.ics.jung.visualization.control.EditingPopupGraphMousePlugin; -import javafx.application.Platform; -import javafx.scene.control.ContextMenu; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.awt.event.MouseEvent; -import java.awt.geom.Point2D; - -public class CorePopupGraphMousePlugin extends EditingPopupGraphMousePlugin { - private static final Logger logger = LogManager.getLogger(); - private final Controller controller; - private final NetworkGraph networkGraph; - private final Layout graphLayout; - private final GraphElementAccessor pickSupport; - - public CorePopupGraphMousePlugin(Controller controller, NetworkGraph networkGraph, - Supplier vertexFactory, Supplier edgeFactory) { - super(vertexFactory, edgeFactory); - this.controller = controller; - this.networkGraph = networkGraph; - graphLayout = this.networkGraph.getGraphLayout(); - pickSupport = this.networkGraph.getGraphViewer().getPickSupport(); - } - - @Override - protected void handlePopup(MouseEvent e) { - logger.info("showing popup!"); - final Point2D p = e.getPoint(); - - final CoreNode node = pickSupport.getVertex(graphLayout, p.getX(), p.getY()); - final CoreLink link = pickSupport.getEdge(graphLayout, p.getX(), p.getY()); - - final ContextMenu contextMenu; - if (node != null) { - contextMenu = handleNodeContext(node); - } else if (link != null) { - contextMenu = new LinkContextMenu(controller, link); - } else { - contextMenu = new ContextMenu(); - } - - if (!contextMenu.getItems().isEmpty()) { - logger.info("showing context menu"); - Platform.runLater(() -> contextMenu.show(controller.getWindow(), - e.getXOnScreen(), e.getYOnScreen())); - } - } - - private ContextMenu handleNodeContext(final CoreNode node) { - ContextMenu contextMenu = new ContextMenu(); - switch (node.getType()) { - case NodeType.DEFAULT: - contextMenu = new NodeContextMenu(controller, node); - break; - case NodeType.WLAN: - contextMenu = new WlanContextMenu(controller, node); - break; - case NodeType.EMANE: - contextMenu = new EmaneContextMenu(controller, node); - break; - default: - logger.warn("no context menu for node: {}", node.getType()); - break; - } - - return contextMenu; - } -} diff --git a/corefx/src/main/java/com/core/graph/CoreVertexLabelRenderer.java b/corefx/src/main/java/com/core/graph/CoreVertexLabelRenderer.java deleted file mode 100644 index 25c49fa3..00000000 --- a/corefx/src/main/java/com/core/graph/CoreVertexLabelRenderer.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.core.graph; - -import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; - -public class CoreVertexLabelRenderer extends DefaultVertexLabelRenderer { - private Color foregroundColor = Color.WHITE; - private Color backgroundColor = Color.BLACK; - - CoreVertexLabelRenderer() { - super(Color.YELLOW); - } - - public void setColors(Color foregroundColor, Color backgroundColor) { - this.foregroundColor = foregroundColor; - this.backgroundColor = backgroundColor; - } - - @Override - public Component getVertexLabelRendererComponent(JComponent vv, Object value, Font font, boolean isSelected, V vertex) { - super.setForeground(foregroundColor); - if (isSelected) { - this.setForeground(this.pickedVertexLabelColor); - } - - super.setBackground(backgroundColor); - if (font != null) { - this.setFont(font); - } else { - this.setFont(vv.getFont()); - } - - this.setIcon(null); - EmptyBorder padding = new EmptyBorder(5, 5, 5, 5); - this.setBorder(padding); - this.setValue(value); - setFont(getFont().deriveFont(Font.BOLD)); - return this; - } -} diff --git a/corefx/src/main/java/com/core/graph/EmaneContextMenu.java b/corefx/src/main/java/com/core/graph/EmaneContextMenu.java deleted file mode 100644 index 848bbfb3..00000000 --- a/corefx/src/main/java/com/core/graph/EmaneContextMenu.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreNode; -import com.core.ui.dialogs.MobilityPlayerDialog; - -class EmaneContextMenu extends AbstractNodeContextMenu { - EmaneContextMenu(Controller controller, CoreNode coreNode) { - super(controller, coreNode); - setup(); - } - - private void setup() { - addMenuItem("EMANE Settings", event -> controller.getNodeEmaneDialog().showDialog(coreNode)); - if (controller.getCoreClient().isRunning()) { - MobilityPlayerDialog mobilityPlayerDialog = controller.getMobilityPlayerDialogs().get(coreNode.getId()); - if (mobilityPlayerDialog != null && !mobilityPlayerDialog.getStage().isShowing()) { - addMenuItem("Mobility Script", event -> mobilityPlayerDialog.show()); - } - } else { - addMenuItem("Mobility", event -> controller.getMobilityDialog().showDialog(coreNode)); - addMenuItem("Link MDRs", event -> controller.getNetworkGraph().linkMdrs(coreNode)); - addMenuItem("Delete Node", event -> controller.deleteNode(coreNode)); - } - } -} diff --git a/corefx/src/main/java/com/core/graph/GraphContextMenu.java b/corefx/src/main/java/com/core/graph/GraphContextMenu.java deleted file mode 100644 index c93ecba9..00000000 --- a/corefx/src/main/java/com/core/graph/GraphContextMenu.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; - -abstract class GraphContextMenu extends ContextMenu { - final Controller controller; - - GraphContextMenu(Controller controller) { - super(); - this.controller = controller; - } - - void addMenuItem(String text, EventHandler handler) { - MenuItem menuItem = new MenuItem(text); - menuItem.setOnAction(handler); - getItems().add(menuItem); - } -} diff --git a/corefx/src/main/java/com/core/graph/LinkContextMenu.java b/corefx/src/main/java/com/core/graph/LinkContextMenu.java deleted file mode 100644 index d9b11115..00000000 --- a/corefx/src/main/java/com/core/graph/LinkContextMenu.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreLink; - -class LinkContextMenu extends GraphContextMenu { - final CoreLink coreLink; - - LinkContextMenu(Controller controller, CoreLink coreLink) { - super(controller); - this.coreLink = coreLink; - setup(); - } - - private void setup() { - if (!controller.getCoreClient().isRunning()) { - addMenuItem("Delete Link", - event -> controller.getNetworkGraph().removeLink(coreLink)); - } - } -} diff --git a/corefx/src/main/java/com/core/graph/NetworkGraph.java b/corefx/src/main/java/com/core/graph/NetworkGraph.java deleted file mode 100644 index 7d55cdb2..00000000 --- a/corefx/src/main/java/com/core/graph/NetworkGraph.java +++ /dev/null @@ -1,492 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.*; -import com.core.ui.Toast; -import com.core.ui.dialogs.TerminalDialog; -import com.core.utils.Configuration; -import com.core.utils.IconUtils; -import com.google.common.base.Supplier; -import edu.uci.ics.jung.algorithms.layout.StaticLayout; -import edu.uci.ics.jung.graph.ObservableGraph; -import edu.uci.ics.jung.graph.event.GraphEvent; -import edu.uci.ics.jung.graph.event.GraphEventListener; -import edu.uci.ics.jung.graph.util.Pair; -import edu.uci.ics.jung.visualization.RenderContext; -import edu.uci.ics.jung.visualization.VisualizationViewer; -import edu.uci.ics.jung.visualization.annotations.AnnotationControls; -import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse; -import edu.uci.ics.jung.visualization.control.GraphMouseListener; -import edu.uci.ics.jung.visualization.control.ModalGraphMouse; -import edu.uci.ics.jung.visualization.decorators.EdgeShape; -import edu.uci.ics.jung.visualization.renderers.Renderer; -import javafx.application.Platform; -import lombok.Data; -import org.apache.commons.net.util.SubnetUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.geom.Ellipse2D; -import java.io.IOException; -import java.util.*; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - - -@Data -public class NetworkGraph { - private static final Logger logger = LogManager.getLogger(); - private static final int EDGE_LABEL_OFFSET = -5; - private static final int EDGE_WIDTH = 5; - private Controller controller; - private ObservableGraph graph; - private StaticLayout graphLayout; - private VisualizationViewer graphViewer; - private EditingModalGraphMouse graphMouse; - private AnnotationControls annotationControls; - - private SubnetUtils subnetUtils = new SubnetUtils("10.0.0.0/24"); - private CoreAddresses coreAddresses = new CoreAddresses("10.0"); - private NodeType nodeType; - private Map nodeMap = new ConcurrentHashMap<>(); - private int vertexId = 1; - private int linkId = 1; - private Supplier vertexFactory = () -> new CoreNode(vertexId++); - private Supplier linkFactory = () -> new CoreLink(linkId++); - private CorePopupGraphMousePlugin customPopupPlugin; - private CoreAnnotatingGraphMousePlugin customAnnotatingPlugin; - private BackgroundPaintable backgroundPaintable; - private CoreVertexLabelRenderer nodeLabelRenderer = new CoreVertexLabelRenderer(); - - // display options - private boolean showThroughput = false; - private Double throughputLimit = null; - private int throughputWidth = 10; - - public NetworkGraph(Controller controller) { - this.controller = controller; - graph = new CoreObservableGraph<>(new UndirectedSimpleGraph<>()); - graph.addGraphEventListener(graphEventListener); - graphLayout = new StaticLayout<>(graph); - graphViewer = new VisualizationViewer<>(graphLayout); - graphViewer.setBackground(Color.WHITE); - graphViewer.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S); - - RenderContext renderContext = graphViewer.getRenderContext(); - - // node render properties - renderContext.setVertexLabelTransformer(CoreNode::getName); - renderContext.setVertexLabelRenderer(nodeLabelRenderer); - renderContext.setVertexShapeTransformer(node -> { - double offset = -(IconUtils.ICON_SIZE / 2.0); - return new Ellipse2D.Double(offset, offset, IconUtils.ICON_SIZE, IconUtils.ICON_SIZE); - }); - renderContext.setVertexIconTransformer(vertex -> { - long wirelessLinks = wirelessLinkCount(vertex); - vertex.getRadioIcon().setWiressLinks(wirelessLinks); - return vertex.getGraphIcon(); - }); - - // link render properties - renderContext.setEdgeLabelTransformer(edge -> { - if (!showThroughput || edge == null) { - return null; - } - double kbps = edge.getThroughput() / 1000.0; - return String.format("%.2f kbps", kbps); - }); - renderContext.setLabelOffset(EDGE_LABEL_OFFSET); - renderContext.setEdgeStrokeTransformer(edge -> { - // determine edge width - int width = EDGE_WIDTH; - if (throughputLimit != null && edge.getThroughput() > throughputLimit) { - width = throughputWidth; - } - - LinkTypes linkType = LinkTypes.get(edge.getType()); - if (LinkTypes.WIRELESS == linkType) { - float[] dash = {15.0f}; - return new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, - 0, dash, 0); - } else { - return new BasicStroke(width); - } - }); - renderContext.setEdgeShapeTransformer(EdgeShape.line(graph)); - renderContext.setEdgeDrawPaintTransformer(edge -> { - LinkTypes linkType = LinkTypes.get(edge.getType()); - if (LinkTypes.WIRELESS == linkType) { - return Color.BLUE; - } else { - return Color.BLACK; - } - }); - renderContext.setEdgeIncludePredicate(predicate -> predicate.element.isVisible()); - - graphViewer.setVertexToolTipTransformer(renderContext.getVertexLabelTransformer()); - graphMouse = new CoreEditingModalGraphMouse<>(controller, this, renderContext, - vertexFactory, linkFactory); - graphViewer.setGraphMouse(graphMouse); - - // mouse events - graphViewer.addGraphMouseListener(new GraphMouseListener() { - @Override - public void graphClicked(CoreNode node, MouseEvent mouseEvent) { - // double click - logger.info("click count: {}, running?: {}", mouseEvent.getClickCount(), - controller.getCoreClient().isRunning()); - - if (mouseEvent.getClickCount() == 2 && controller.getCoreClient().isRunning()) { - if (controller.getCoreClient().isLocalConnection()) { - try { - String shellCommand = controller.getConfiguration().getShellCommand(); - String terminalCommand = controller.getCoreClient().getTerminalCommand(node); - terminalCommand = String.format("%s %s", shellCommand, terminalCommand); - logger.info("launching node terminal: {}", terminalCommand); - String[] commands = terminalCommand.split("\\s+"); - logger.info("launching node terminal: {}", Arrays.toString(commands)); - Process p = new ProcessBuilder(commands).start(); - try { - if (!p.waitFor(5, TimeUnit.SECONDS)) { - Toast.error("Node terminal command failed"); - } - } catch (InterruptedException ex) { - logger.error("error waiting for terminal to start", ex); - } - } catch (IOException ex) { - logger.error("error launching terminal", ex); - Toast.error("Node terminal failed to start"); - } - } else { - Platform.runLater(() -> { - TerminalDialog terminalDialog = new TerminalDialog(controller); - terminalDialog.setOwner(controller.getWindow()); - terminalDialog.showDialog(node); - }); - } - } - } - - @Override - public void graphPressed(CoreNode node, MouseEvent mouseEvent) { - logger.debug("graph pressed: {} - {}", node, mouseEvent); - } - - @Override - public void graphReleased(CoreNode node, MouseEvent mouseEvent) { - if (SwingUtilities.isLeftMouseButton(mouseEvent)) { - Double newX = graphLayout.getX(node); - Double newY = graphLayout.getY(node); - Double oldX = node.getPosition().getX(); - Double oldY = node.getPosition().getY(); - if (newX.equals(oldX) && newY.equals(oldY)) { - return; - } - logger.debug("graph moved node({}): {},{}", node.getName(), newX, newY); - node.getPosition().setX(newX); - node.getPosition().setY(newY); - - // upate node when session is active - if (controller.getCoreClient().isRunning()) { - try { - controller.getCoreClient().editNode(node); - } catch (IOException ex) { - Toast.error("failed to update node location"); - } - } - } - } - }); - } - - private Color convertJfxColor(String hexValue) { - javafx.scene.paint.Color color = javafx.scene.paint.Color.web(hexValue); - return new Color((float) color.getRed(), (float) color.getGreen(), (float) color.getBlue()); - } - - public void updatePreferences(Configuration configuration) { - Color nodeLabelColor = convertJfxColor(configuration.getNodeLabelColor()); - Color nodeLabelBackgroundColor = convertJfxColor(configuration.getNodeLabelBackgroundColor()); - nodeLabelRenderer.setColors(nodeLabelColor, nodeLabelBackgroundColor); - throughputLimit = configuration.getThroughputLimit(); - if (configuration.getThroughputWidth() != null) { - throughputWidth = configuration.getThroughputWidth(); - } - graphViewer.repaint(); - } - - public void setBackground(String imagePath) { - try { - backgroundPaintable = new BackgroundPaintable<>(imagePath, graphViewer); - graphViewer.addPreRenderPaintable(backgroundPaintable); - graphViewer.repaint(); - } catch (IOException ex) { - logger.error("error setting background", ex); - } - } - - public void removeBackground() { - if (backgroundPaintable != null) { - graphViewer.removePreRenderPaintable(backgroundPaintable); - graphViewer.repaint(); - backgroundPaintable = null; - } - } - - public void setMode(ModalGraphMouse.Mode mode) { - graphMouse.setMode(mode); - } - - public void reset() { - logger.info("network graph reset"); - vertexId = 1; - linkId = 1; - for (CoreNode node : nodeMap.values()) { - graph.removeVertex(node); - } - nodeMap.clear(); - graphViewer.repaint(); - } - - public void updatePositions() { - for (CoreNode node : graph.getVertices()) { - Double x = graphLayout.getX(node); - Double y = graphLayout.getY(node); - node.getPosition().setX(x); - node.getPosition().setY(y); - logger.debug("updating node position node({}): {},{}", node, x, y); - } - } - - public CoreNode getVertex(int id) { - return nodeMap.get(id); - } - - private GraphEventListener graphEventListener = graphEvent -> { - logger.info("graph event: {}", graphEvent.getType()); - switch (graphEvent.getType()) { - case EDGE_ADDED: - handleEdgeAdded((GraphEvent.Edge) graphEvent); - break; - case EDGE_REMOVED: - handleEdgeRemoved((GraphEvent.Edge) graphEvent); - break; - case VERTEX_ADDED: - handleVertexAdded((GraphEvent.Vertex) graphEvent); - break; - case VERTEX_REMOVED: - handleVertexRemoved((GraphEvent.Vertex) graphEvent); - break; - } - }; - - private void handleEdgeAdded(GraphEvent.Edge edgeEvent) { - CoreLink link = edgeEvent.getEdge(); - if (!link.isLoaded()) { - Pair endpoints = graph.getEndpoints(link); - - CoreNode nodeOne = endpoints.getFirst(); - CoreNode nodeTwo = endpoints.getSecond(); - - // create interfaces for nodes - int sub = coreAddresses.getSubnet( - getInterfaces(nodeOne), - getInterfaces(nodeTwo) - ); - - link.setNodeOne(nodeOne.getId()); - if (isNode(nodeOne)) { - int interfaceOneId = nextInterfaceId(nodeOne); - CoreInterface interfaceOne = createInterface(nodeOne, sub, interfaceOneId); - link.setInterfaceOne(interfaceOne); - } - - link.setNodeTwo(nodeTwo.getId()); - if (isNode(nodeTwo)) { - int interfaceTwoId = nextInterfaceId(nodeTwo); - CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId); - link.setInterfaceTwo(interfaceTwo); - } - - boolean isVisible = !checkForWirelessNode(nodeOne, nodeTwo); - link.setVisible(isVisible); - - logger.info("adding user created edge: {}", link); - } - } - - public List getInterfaces(CoreNode node) { - return graph.getIncidentEdges(node).stream() - .map(link -> { - if (node.getId().equals(link.getNodeOne())) { - return link.getInterfaceOne(); - } else { - return link.getInterfaceTwo(); - } - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private int nextInterfaceId(CoreNode node) { - Set interfaceIds = graph.getIncidentEdges(node).stream() - .map(link -> { - if (node.getId().equals(link.getNodeOne())) { - return link.getInterfaceOne(); - } else { - return link.getInterfaceTwo(); - } - }) - .filter(Objects::nonNull) - .map(CoreInterface::getId) - .collect(Collectors.toSet()); - - int i = 0; - while (true) { - if (!interfaceIds.contains(i)) { - return i; - } - - i += 1; - } - } - - private boolean isNode(CoreNode node) { - return node.getType() == NodeType.DEFAULT; - } - - private CoreInterface createInterface(CoreNode node, int sub, int interfaceId) { - CoreInterface coreInterface = new CoreInterface(); - coreInterface.setId(interfaceId); - coreInterface.setName(String.format("eth%s", interfaceId)); - String nodeOneIp4 = coreAddresses.getIp4Address(sub, node.getId()); - coreInterface.setIp4(nodeOneIp4); - coreInterface.setIp4Mask(CoreAddresses.IP4_MASK); - return coreInterface; - } - - private void handleEdgeRemoved(GraphEvent.Edge edgeEvent) { - CoreLink link = edgeEvent.getEdge(); - logger.info("removed edge: {}", link); - } - - private void handleVertexAdded(GraphEvent.Vertex vertexEvent) { - CoreNode node = vertexEvent.getVertex(); - if (!node.isLoaded()) { - node.setNodeType(nodeType); - if (node.getType() == NodeType.EMANE) { - String emaneModel = controller.getNodeEmaneDialog().getModels().get(0); - node.setEmane(emaneModel); - } - - logger.info("adding user created node: {}", node); - nodeMap.put(node.getId(), node); - } - } - - private void handleVertexRemoved(GraphEvent.Vertex vertexEvent) { - CoreNode node = vertexEvent.getVertex(); - logger.info("removed vertex: {}", node); - nodeMap.remove(node.getId()); - } - - public void addNode(CoreNode node) { - vertexId = Math.max(node.getId() + 1, node.getId()); - double x = Math.abs(node.getPosition().getX()); - double y = Math.abs(node.getPosition().getY()); - logger.info("adding session node: {}", node); - graph.addVertex(node); - graphLayout.setLocation(node, x, y); - nodeMap.put(node.getId(), node); - } - - public void setNodeLocation(CoreNode nodeData) { - // update actual graph node - CoreNode node = nodeMap.get(nodeData.getId()); - node.getPosition().setX(nodeData.getPosition().getX()); - node.getPosition().setY(nodeData.getPosition().getY()); - - // set graph node location - double x = Math.abs(node.getPosition().getX()); - double y = Math.abs(node.getPosition().getY()); - graphLayout.setLocation(node, x, y); - graphViewer.repaint(); - } - - public void removeNode(CoreNode node) { - try { - controller.getCoreClient().deleteNode(node); - } catch (IOException ex) { - logger.error("error deleting node"); - Toast.error(String.format("Error deleting node: %s", node.getName())); - } - graphViewer.getPickedVertexState().pick(node, false); - graph.removeVertex(node); - graphViewer.repaint(); - } - - private boolean isWirelessNode(CoreNode node) { - return node.getType() == NodeType.EMANE || node.getType() == NodeType.WLAN; - } - - private boolean checkForWirelessNode(CoreNode nodeOne, CoreNode nodeTwo) { - boolean result = isWirelessNode(nodeOne); - return result || isWirelessNode(nodeTwo); - } - - private long wirelessLinkCount(CoreNode node) { - return graph.getNeighbors(node).stream() - .filter(this::isWirelessNode) - .count(); - } - - public void addLink(CoreLink link) { - logger.info("adding session link: {}", link); - link.setId(linkId++); - CoreNode nodeOne = nodeMap.get(link.getNodeOne()); - CoreNode nodeTwo = nodeMap.get(link.getNodeTwo()); - - boolean isVisible = !checkForWirelessNode(nodeOne, nodeTwo); - link.setVisible(isVisible); - - graph.addEdge(link, nodeOne, nodeTwo); - } - - public void removeWirelessLink(CoreLink link) { - logger.info("deleting link: {}", link); - CoreNode nodeOne = nodeMap.get(link.getNodeOne()); - CoreNode nodeTwo = nodeMap.get(link.getNodeTwo()); - - CoreLink existingLink = graph.findEdge(nodeOne, nodeTwo); - if (existingLink != null) { - graph.removeEdge(existingLink); - } - } - - public void removeLink(CoreLink link) { - graphViewer.getPickedEdgeState().pick(link, false); - graph.removeEdge(link); - graphViewer.repaint(); - } - - public void linkMdrs(CoreNode node) { - for (CoreNode currentNode : graph.getVertices()) { - if (!"mdr".equals(currentNode.getModel())) { - continue; - } - - // only links mdrs we have not already linked - Collection links = graph.findEdgeSet(node, currentNode); - if (links.isEmpty()) { - CoreLink link = linkFactory.get(); - graph.addEdge(link, currentNode, node); - graphViewer.repaint(); - } - } - } -} diff --git a/corefx/src/main/java/com/core/graph/NodeContextMenu.java b/corefx/src/main/java/com/core/graph/NodeContextMenu.java deleted file mode 100644 index d50cd58a..00000000 --- a/corefx/src/main/java/com/core/graph/NodeContextMenu.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreNode; -import com.core.ui.Toast; -import javafx.scene.control.Menu; -import javafx.scene.control.MenuItem; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.util.Collections; -import java.util.Set; - -class NodeContextMenu extends AbstractNodeContextMenu { - private static final Logger logger = LogManager.getLogger(); - - NodeContextMenu(Controller controller, CoreNode coreNode) { - super(controller, coreNode); - setup(); - } - - private MenuItem createStartItem(String service) { - MenuItem menuItem = new MenuItem("Start"); - menuItem.setOnAction(event -> { - try { - boolean result = controller.getCoreClient().startService(coreNode, service); - if (result) { - Toast.success("Started " + service); - } else { - Toast.error("Failure to start " + service); - } - } catch (IOException ex) { - Toast.error("Error starting " + service, ex); - } - }); - return menuItem; - } - - private MenuItem createStopItem(String service) { - MenuItem menuItem = new MenuItem("Stop"); - menuItem.setOnAction(event -> { - try { - boolean result = controller.getCoreClient().stopService(coreNode, service); - if (result) { - Toast.success("Stopped " + service); - } else { - Toast.error("Failure to stop " + service); - } - } catch (IOException ex) { - Toast.error("Error stopping " + service, ex); - } - }); - return menuItem; - } - - private MenuItem createRestartItem(String service) { - MenuItem menuItem = new MenuItem("Restart"); - menuItem.setOnAction(event -> { - try { - boolean result = controller.getCoreClient().restartService(coreNode, service); - if (result) { - Toast.success("Restarted " + service); - } else { - Toast.error("Failure to restart " + service); - } - } catch (IOException ex) { - Toast.error("Error restarting " + service, ex); - } - }); - return menuItem; - } - - private MenuItem createValidateItem(String service) { - MenuItem menuItem = new MenuItem("Validate"); - menuItem.setOnAction(event -> { - try { - boolean result = controller.getCoreClient().validateService(coreNode, service); - if (result) { - Toast.success("Validated " + service); - } else { - Toast.error("Validation failed for " + service); - } - } catch (IOException ex) { - Toast.error("Error validating " + service, ex); - } - }); - return menuItem; - } - - private void setup() { - if (controller.getCoreClient().isRunning()) { - Set services = coreNode.getServices(); - if (services.isEmpty()) { - services = controller.getDefaultServices().getOrDefault(coreNode.getModel(), Collections.emptySet()); - } - - if (!services.isEmpty()) { - Menu menu = new Menu("Manage Services"); - for (String service : services) { - Menu serviceMenu = new Menu(service); - MenuItem startItem = createStartItem(service); - MenuItem stopItem = createStopItem(service); - MenuItem restartItem = createRestartItem(service); - MenuItem validateItem = createValidateItem(service); - serviceMenu.getItems().addAll(startItem, stopItem, restartItem, validateItem); - menu.getItems().add(serviceMenu); - } - getItems().add(menu); - } - } else { - addMenuItem("Services", event -> controller.getNodeServicesDialog().showDialog(coreNode)); - addMenuItem("Delete Node", event -> controller.deleteNode(coreNode)); - } - } -} diff --git a/corefx/src/main/java/com/core/graph/RadioIcon.java b/corefx/src/main/java/com/core/graph/RadioIcon.java deleted file mode 100644 index e3139eaf..00000000 --- a/corefx/src/main/java/com/core/graph/RadioIcon.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.core.graph; - -import com.core.utils.IconUtils; -import lombok.Data; - -import javax.swing.*; -import java.awt.*; - -@Data -public class RadioIcon implements Icon { - private long wiressLinks = 0; - - @Override - public int getIconHeight() { - return IconUtils.ICON_SIZE; - } - - @Override - public int getIconWidth() { - return IconUtils.ICON_SIZE; - } - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(Color.black); - for (int i = 0; i < wiressLinks; i++) { - g.fillOval(x, y, 10, 10); - x += 15; - } - } -} diff --git a/corefx/src/main/java/com/core/graph/UndirectedSimpleGraph.java b/corefx/src/main/java/com/core/graph/UndirectedSimpleGraph.java deleted file mode 100644 index 355b44a0..00000000 --- a/corefx/src/main/java/com/core/graph/UndirectedSimpleGraph.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.core.graph; - -import edu.uci.ics.jung.graph.UndirectedSparseGraph; -import edu.uci.ics.jung.graph.util.EdgeType; -import edu.uci.ics.jung.graph.util.Pair; - -public class UndirectedSimpleGraph extends UndirectedSparseGraph { - @Override - public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) { - Pair newEndpoints = getValidatedEndpoints(edge, endpoints); - if (newEndpoints == null) { - return false; - } - - V first = newEndpoints.getFirst(); - V second = newEndpoints.getSecond(); - - if (first.equals(second)) { - return false; - } else { - return super.addEdge(edge, endpoints, edgeType); - } - } -} diff --git a/corefx/src/main/java/com/core/graph/WlanContextMenu.java b/corefx/src/main/java/com/core/graph/WlanContextMenu.java deleted file mode 100644 index 937eef15..00000000 --- a/corefx/src/main/java/com/core/graph/WlanContextMenu.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.core.graph; - -import com.core.Controller; -import com.core.data.CoreNode; -import com.core.ui.dialogs.MobilityPlayerDialog; - -class WlanContextMenu extends AbstractNodeContextMenu { - WlanContextMenu(Controller controller, CoreNode coreNode) { - super(controller, coreNode); - setup(); - } - - private void setup() { - addMenuItem("WLAN Settings", event -> controller.getNodeWlanDialog().showDialog(coreNode)); - if (controller.getCoreClient().isRunning()) { - MobilityPlayerDialog mobilityPlayerDialog = controller.getMobilityPlayerDialogs().get(coreNode.getId()); - if (mobilityPlayerDialog != null && !mobilityPlayerDialog.getStage().isShowing()) { - addMenuItem("Mobility Script", event -> mobilityPlayerDialog.show()); - } - } else { - addMenuItem("Mobility", event -> controller.getMobilityDialog().showDialog(coreNode)); - addMenuItem("Link MDRs", event -> controller.getNetworkGraph().linkMdrs(coreNode)); - addMenuItem("Delete Node", event -> controller.deleteNode(coreNode)); - } - } -} diff --git a/corefx/src/main/java/com/core/ui/AnnotationToolbar.java b/corefx/src/main/java/com/core/ui/AnnotationToolbar.java deleted file mode 100644 index b32d3c8b..00000000 --- a/corefx/src/main/java/com/core/ui/AnnotationToolbar.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.core.ui; - -import com.core.graph.NetworkGraph; -import com.core.utils.FxmlUtils; -import com.jfoenix.controls.JFXColorPicker; -import com.jfoenix.controls.JFXComboBox; -import com.jfoenix.controls.JFXToggleButton; -import edu.uci.ics.jung.visualization.annotations.Annotation; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.layout.GridPane; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.awt.*; -import java.awt.geom.Ellipse2D; -import java.awt.geom.RectangularShape; -import java.awt.geom.RoundRectangle2D; - -public class AnnotationToolbar extends GridPane { - private static final Logger logger = LogManager.getLogger(); - private static final String RECTANGLE = "Rectangle"; - private static final String ROUND_RECTANGLE = "RoundRectangle"; - private static final String ELLIPSE = "Ellipse"; - private static final String UPPER_LAYER = "Upper"; - private static final String LOWER_LAYER = "Lower"; - private NetworkGraph graph; - @FXML private JFXComboBox shapeCombo; - @FXML private JFXColorPicker colorPicker; - @FXML private JFXComboBox layerCombo; - @FXML private JFXToggleButton fillToggle; - - public AnnotationToolbar(NetworkGraph graph) { - this.graph = graph; - FxmlUtils.loadRootController(this, "/fxml/annotation_toolbar.fxml"); - - // setup annotation shape combo - shapeCombo.getItems().addAll(RECTANGLE, ROUND_RECTANGLE, ELLIPSE); - shapeCombo.setOnAction(this::shapeChange); - shapeCombo.getSelectionModel().selectFirst(); - - // setup annotation layer combo - layerCombo.getItems().addAll(LOWER_LAYER, UPPER_LAYER); - layerCombo.setOnAction(this::layerChange); - layerCombo.getSelectionModel().selectFirst(); - - // setup annotation color picker - colorPicker.setOnAction(this::colorChange); - colorPicker.setValue(javafx.scene.paint.Color.AQUA); - colorPicker.fireEvent(new ActionEvent()); - - // setup annotation toggle fill - fillToggle.setOnAction(this::fillChange); - } - - private void fillChange(ActionEvent event) { - boolean selected = fillToggle.isSelected(); - graph.getGraphMouse().getAnnotatingPlugin().setFill(selected); - } - - private void colorChange(ActionEvent event) { - javafx.scene.paint.Color fxColor = colorPicker.getValue(); - java.awt.Color color = new java.awt.Color( - (float) fxColor.getRed(), - (float) fxColor.getGreen(), - (float) fxColor.getBlue(), - (float) fxColor.getOpacity() - ); - logger.info("color selected: {}", fxColor); - graph.getGraphMouse().getAnnotatingPlugin().setAnnotationColor(color); - } - - private void layerChange(ActionEvent event) { - String selected = layerCombo.getSelectionModel().getSelectedItem(); - logger.info("annotation layer selected: {}", selected); - Annotation.Layer layer; - if (LOWER_LAYER.equals(selected)) { - layer = Annotation.Layer.LOWER; - } else { - layer = Annotation.Layer.UPPER; - } - graph.getGraphMouse().getAnnotatingPlugin().setLayer(layer); - } - - private void shapeChange(ActionEvent event) { - String selected = shapeCombo.getSelectionModel().getSelectedItem(); - logger.info("annotation shape selected: {}", selected); - RectangularShape shape = new Rectangle(); - switch (selected) { - case RECTANGLE: - shape = new Rectangle(); - break; - case ROUND_RECTANGLE: - shape = new RoundRectangle2D.Double(0, 0, 0, 0, 50.0, 50.0); - break; - case ELLIPSE: - shape = new Ellipse2D.Double(); - break; - default: - Toast.error("Unknown annotation shape " + selected); - } - graph.getGraphMouse().getAnnotatingPlugin().setRectangularShape(shape); - } -} diff --git a/corefx/src/main/java/com/core/ui/GraphToolbar.java b/corefx/src/main/java/com/core/ui/GraphToolbar.java deleted file mode 100644 index f64ca73a..00000000 --- a/corefx/src/main/java/com/core/ui/GraphToolbar.java +++ /dev/null @@ -1,297 +0,0 @@ -package com.core.ui; - -import com.core.Controller; -import com.core.data.NodeType; -import com.core.utils.FxmlUtils; -import com.core.utils.IconUtils; -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXListView; -import com.jfoenix.controls.JFXPopup; -import com.jfoenix.svg.SVGGlyph; -import edu.uci.ics.jung.visualization.control.ModalGraphMouse; -import javafx.application.Platform; -import javafx.css.PseudoClass; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.Tooltip; -import javafx.scene.image.ImageView; -import javafx.scene.layout.VBox; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; - -public class GraphToolbar extends VBox { - private static final Logger logger = LogManager.getLogger(); - private static final int ICON_SIZE = 40; - private static final int NODES_ICON_SIZE = 20; - private static final PseudoClass START_CLASS = PseudoClass.getPseudoClass("start"); - private static final PseudoClass STOP_CLASS = PseudoClass.getPseudoClass("stop"); - private static final PseudoClass SELECTED_CLASS = PseudoClass.getPseudoClass("selected"); - private final Controller controller; - private final Map labelMap = new HashMap<>(); - private SVGGlyph startIcon; - private SVGGlyph stopIcon; - private JFXListView