Merge pull request #490 from coreemu/enhancement/poetry-invoke

Enhancement/poetry invoke
This commit is contained in:
bharnden 2020-07-15 14:44:04 -07:00 committed by GitHub
commit feb81ae876
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 1737 additions and 1518 deletions

View file

@ -11,32 +11,31 @@ jobs:
uses: actions/setup-python@v1 uses: actions/setup-python@v1
with: with:
python-version: 3.6 python-version: 3.6
- name: Install pipenv - name: install poetry
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install pipenv pip install poetry
cd daemon cd daemon
cp setup.py.in setup.py
cp core/constants.py.in core/constants.py cp core/constants.py.in core/constants.py
sed -i 's/required=True/required=False/g' core/emulator/coreemu.py sed -i 's/required=True/required=False/g' core/emulator/coreemu.py
pipenv sync --dev poetry install
- name: isort - name: isort
run: | run: |
cd daemon cd daemon
pipenv run isort -c -df poetry run isort -c -df
- name: black - name: black
run: | run: |
cd daemon cd daemon
pipenv run black --check --exclude ".+_pb2.*.py|doc|build|utm\.py|setup\.py" . poetry run black --check .
- name: flake8 - name: flake8
run: | run: |
cd daemon cd daemon
pipenv run flake8 poetry run flake8
- name: grpc - name: grpc
run: | run: |
cd daemon/proto cd daemon/proto
pipenv run python -m grpc_tools.protoc -I . --python_out=.. --grpc_python_out=.. core/api/grpc/*.proto poetry run python -m grpc_tools.protoc -I . --python_out=.. --grpc_python_out=.. core/api/grpc/*.proto
- name: test - name: test
run: | run: |
cd daemon cd daemon
pipenv run test --mock poetry run pytest --mock tests

4
.gitignore vendored
View file

@ -39,6 +39,7 @@ coverage.xml
# python files # python files
*.egg-info *.egg-info
*.pyc
# ignore package files # ignore package files
*.rpm *.rpm
@ -55,8 +56,5 @@ coverage.xml
netns/setup.py netns/setup.py
daemon/setup.py daemon/setup.py
# ignore corefx build
corefx/target
# python # python
__pycache__ __pycache__

View file

@ -11,7 +11,7 @@ if WANT_GUI
endif endif
if WANT_DAEMON if WANT_DAEMON
DAEMON = scripts daemon DAEMON = daemon
endif endif
if WANT_NETNS if WANT_NETNS
@ -44,58 +44,6 @@ DISTCLEANFILES = aclocal.m4 \
MAINTAINERCLEANFILES = .version \ MAINTAINERCLEANFILES = .version \
.version.date .version.date
define fpm-rpm =
fpm -s dir -t rpm -n core \
-m "$(PACKAGE_MAINTAINERS)" \
--license "BSD" \
--description "Common Open Research Emulator" \
--url https://github.com/coreemu/core \
--vendor "$(PACKAGE_VENDOR)" \
-p core_VERSION_ARCH.rpm \
-v $(PACKAGE_VERSION) \
--rpm-init scripts/core-daemon \
--config-files "/etc/core" \
-d "ethtool" \
-d "tcl" \
-d "tk" \
-d "procps-ng" \
-d "bash >= 3.0" \
-d "ebtables" \
-d "iproute" \
-d "libev" \
-d "net-tools" \
-d "python3 >= 3.6" \
-d "python3-tkinter" \
-C $(DESTDIR)
endef
define fpm-deb =
fpm -s dir -t deb -n core \
-m "$(PACKAGE_MAINTAINERS)" \
--license "BSD" \
--description "Common Open Research Emulator" \
--url https://github.com/coreemu/core \
--vendor "$(PACKAGE_VENDOR)" \
-p core_VERSION_ARCH.deb \
-v $(PACKAGE_VERSION) \
--deb-systemd scripts/core-daemon.service \
--deb-no-default-config-files \
--config-files "/etc/core" \
-d "ethtool" \
-d "tcl" \
-d "tk" \
-d "libtk-img" \
-d "procps" \
-d "libc6 >= 2.14" \
-d "bash >= 3.0" \
-d "ebtables" \
-d "iproute2" \
-d "libev4" \
-d "python3 >= 3.6" \
-d "python3-tk" \
-C $(DESTDIR)
endef
define fpm-distributed-deb = define fpm-distributed-deb =
fpm -s dir -t deb -n core-distributed \ fpm -s dir -t deb -n core-distributed \
-m "$(PACKAGE_MAINTAINERS)" \ -m "$(PACKAGE_MAINTAINERS)" \
@ -138,12 +86,6 @@ fpm -s dir -t rpm -n core-distributed \
-C $(DESTDIR) -C $(DESTDIR)
endef endef
.PHONY: fpm
fpm: clean-local-fpm
$(MAKE) install DESTDIR=$(DESTDIR)
$(call fpm-deb)
$(call fpm-rpm)
.PHONY: fpm-distributed .PHONY: fpm-distributed
fpm-distributed: clean-local-fpm fpm-distributed: clean-local-fpm
$(MAKE) -C netns install DESTDIR=$(DESTDIR) $(MAKE) -C netns install DESTDIR=$(DESTDIR)
@ -182,11 +124,8 @@ all: change-files
.PHONY: change-files .PHONY: change-files
change-files: change-files:
$(call change-files,gui/core-gui) $(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,daemon/core/constants.py)
$(call change-files,netns/setup.py) $(call change-files,netns/setup.py)
$(call change-files,daemon/setup.py)
CORE_DOC_SRC = core-python-$(PACKAGE_VERSION) CORE_DOC_SRC = core-python-$(PACKAGE_VERSION)
.PHONY: doc .PHONY: doc

View file

@ -167,18 +167,6 @@ if test "x$enable_daemon" = "xyes"; then
if test "x$ovs_of_path" = "xno" ; then if test "x$ovs_of_path" = "xno" ; then
AC_MSG_WARN([Could not locate ovs-ofctl cannot use OVS mode]) AC_MSG_WARN([Could not locate ovs-ofctl cannot use OVS mode])
fi 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
fi fi
if [ test "x$enable_daemon" = "xyes" || test "x$enable_vnodedonly" = "xyes" ] ; then if [ test "x$enable_daemon" = "xyes" || test "x$enable_vnodedonly" = "xyes" ] ; then
@ -220,22 +208,12 @@ if [test "x$want_python" = "xyes" && test "x$enable_docs" = "xyes"] ; then
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])]) 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 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 # Variable substitutions
AM_CONDITIONAL(WANT_GUI, test x$enable_gui = xyes) AM_CONDITIONAL(WANT_GUI, test x$enable_gui = xyes)
AM_CONDITIONAL(WANT_DAEMON, test x$enable_daemon = xyes) AM_CONDITIONAL(WANT_DAEMON, test x$enable_daemon = xyes)
AM_CONDITIONAL(WANT_DOCS, test x$want_docs = xyes) AM_CONDITIONAL(WANT_DOCS, test x$want_docs = xyes)
AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes) AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes)
AM_CONDITIONAL(WANT_NETNS, test x$want_linux_netns = 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) AM_CONDITIONAL(WANT_VNODEDONLY, test x$enable_vnodedonly = xyes)
if test $cross_compiling = no; then if test $cross_compiling = no; then
@ -249,7 +227,6 @@ AC_CONFIG_FILES([Makefile
gui/version.tcl gui/version.tcl
gui/Makefile gui/Makefile
gui/icons/Makefile gui/icons/Makefile
scripts/Makefile
man/Makefile man/Makefile
docs/Makefile docs/Makefile
daemon/Makefile daemon/Makefile
@ -279,9 +256,6 @@ Daemon:
Daemon path: ${bindir} Daemon path: ${bindir}
Daemon config: ${CORE_CONF_DIR} Daemon config: ${CORE_CONF_DIR}
Python: ${PYTHON} Python: ${PYTHON}
Logs: ${CORE_STATE_DIR}/log
Startup: ${with_startup}
Features to build: Features to build:
Build GUI: ${enable_gui} Build GUI: ${enable_gui}

2
daemon/.gitignore vendored
View file

@ -1,2 +0,0 @@
*.pyc
build

View file

@ -5,19 +5,19 @@ repos:
name: isort name: isort
stages: [commit] stages: [commit]
language: system language: system
entry: bash -c 'cd daemon && pipenv run isort --atomic -y' entry: bash -c 'cd daemon && poetry run isort --atomic -y'
types: [python] types: [python]
- id: black - id: black
name: black name: black
stages: [commit] stages: [commit]
language: system language: system
entry: bash -c 'cd daemon && pipenv run black --exclude ".+_pb2.*.py|doc|build|utm\.py" .' entry: bash -c 'cd daemon && poetry run black .'
types: [python] types: [python]
- id: flake8 - id: flake8
name: flake8 name: flake8
stages: [commit] stages: [commit]
language: system language: system
entry: bash -c 'cd daemon && pipenv run flake8' entry: bash -c 'cd daemon && poetry run flake8'
types: [python] types: [python]

View file

@ -1,2 +0,0 @@
graft core/gui/data
graft core/configservices/*/templates

View file

@ -7,43 +7,12 @@
# Makefile for building netns components. # Makefile for building netns components.
# #
SETUPPY = setup.py
SETUPPYFLAGS = -v
if WANT_DOCS if WANT_DOCS
DOCS = doc DOCS = doc
endif endif
SUBDIRS = proto $(DOCS) SUBDIRS = proto $(DOCS)
SCRIPT_FILES := $(notdir $(wildcard scripts/*))
MAN_FILES := $(notdir $(wildcard ../man/*.1))
# Python package build
noinst_SCRIPTS = build
build:
$(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) build
# Python package install
install-exec-hook:
$(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \
--root=/$(DESTDIR) \
--prefix=$(prefix) \
--single-version-externally-managed
# Python package uninstall
uninstall-hook:
rm -rf $(DESTDIR)/etc/core
rm -rf $(DESTDIR)/$(datadir)/core
rm -f $(addprefix $(DESTDIR)/$(datarootdir)/man/man1/, $(MAN_FILES))
rm -f $(addprefix $(DESTDIR)/$(bindir)/,$(SCRIPT_FILES))
rm -rf $(DESTDIR)/$(pythondir)/core-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info
rm -rf $(DESTDIR)/$(pythondir)/core
# Python package cleanup
clean-local:
-rm -rf build
# because we include entire directories with EXTRA_DIST, we need to clean up # because we include entire directories with EXTRA_DIST, we need to clean up
# the source control files # the source control files
dist-hook: dist-hook:
@ -52,17 +21,15 @@ dist-hook:
distclean-local: distclean-local:
-rm -rf core.egg-info -rm -rf core.egg-info
DISTCLEANFILES = Makefile.in DISTCLEANFILES = Makefile.in
# files to include with distribution tarball # files to include with distribution tarball
EXTRA_DIST = $(SETUPPY) \ EXTRA_DIST = core \
core \
data \ data \
doc/conf.py.in \ doc/conf.py.in \
examples \ examples \
scripts \ scripts \
tests \ tests \
test.py \
setup.cfg \ setup.cfg \
requirements.txt poetry.lock \
pyproject.toml

View file

@ -1,23 +0,0 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[scripts]
core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf"
core-pygui = "python scripts/core-pygui"
test = "pytest -v tests"
test-mock = "pytest -v --mock tests"
test-emane = "pytest -v tests/emane"
[dev-packages]
grpcio-tools = "*"
isort = "*"
pre-commit = "*"
flake8 = "*"
black = "==19.3b0"
pytest = "*"
mock = "*"
[packages]
core = {editable = true,path = "."}

732
daemon/Pipfile.lock generated
View file

@ -1,732 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "199897f713f6f338316b33fcbbe0001e9e55fcd5e5e24b2245a89454ce13321f"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"bcrypt": {
"hashes": [
"sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89",
"sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42",
"sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294",
"sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161",
"sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752",
"sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31",
"sha256:6fe49a60b25b584e2f4ef175b29d3a83ba63b3a4df1b4c0605b826668d1b6be5",
"sha256:74a015102e877d0ccd02cdeaa18b32aa7273746914a6c5d0456dd442cb65b99c",
"sha256:763669a367869786bb4c8fcf731f4175775a5b43f070f50f46f0b59da45375d0",
"sha256:8b10acde4e1919d6015e1df86d4c217d3b5b01bb7744c36113ea43d529e1c3de",
"sha256:9fe92406c857409b70a38729dbdf6578caf9228de0aef5bc44f859ffe971a39e",
"sha256:a190f2a5dbbdbff4b74e3103cef44344bc30e61255beb27310e2aec407766052",
"sha256:a595c12c618119255c90deb4b046e1ca3bcfad64667c43d1166f2b04bc72db09",
"sha256:c9457fa5c121e94a58d6505cadca8bed1c64444b83b3204928a866ca2e599105",
"sha256:cb93f6b2ab0f6853550b74e051d297c27a638719753eb9ff66d1e4072be67133",
"sha256:ce4e4f0deb51d38b1611a27f330426154f2980e66582dc5f438aad38b5f24fc1",
"sha256:d7bdc26475679dd073ba0ed2766445bb5b20ca4793ca0db32b399dccc6bc84b7",
"sha256:ff032765bb8716d9387fd5376d987a937254b0619eff0972779515b5c98820bc"
],
"version": "==3.1.7"
},
"cffi": {
"hashes": [
"sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
"sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
"sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
"sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
"sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
"sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
"sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
"sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
"sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
"sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
"sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
"sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
"sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
"sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
"sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
"sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
"sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
"sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
"sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
"sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
"sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
"sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
"sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
"sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
"sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
"sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
"sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
"sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
],
"version": "==1.14.0"
},
"core": {
"editable": true,
"path": "."
},
"cryptography": {
"hashes": [
"sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c",
"sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595",
"sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad",
"sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651",
"sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2",
"sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff",
"sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d",
"sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42",
"sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d",
"sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e",
"sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912",
"sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793",
"sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13",
"sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7",
"sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0",
"sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879",
"sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f",
"sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9",
"sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2",
"sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf",
"sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"
],
"version": "==2.8"
},
"dataclasses": {
"hashes": [
"sha256:3459118f7ede7c8bea0fe795bff7c6c2ce287d01dd226202f7c9ebc0610a7836",
"sha256:494a6dcae3b8bcf80848eea2ef64c0cc5cd307ffc263e17cdf42f3e5420808e6"
],
"index": "pypi",
"markers": "python_version == '3.6'",
"version": "==0.7"
},
"fabric": {
"hashes": [
"sha256:160331934ea60036604928e792fa8e9f813266b098ef5562aa82b88527740389",
"sha256:24842d7d51556adcabd885ac3cf5e1df73fc622a1708bf3667bf5927576cdfa6"
],
"version": "==2.5.0"
},
"grpcio": {
"hashes": [
"sha256:02aef8ef1a5ac5f0836b543e462eb421df6048a7974211a906148053b8055ea6",
"sha256:07f82aefb4a56c7e1e52b78afb77d446847d27120a838a1a0489260182096045",
"sha256:1cff47297ee614e7ef66243dc34a776883ab6da9ca129ea114a802c5e58af5c1",
"sha256:1ec8fc865d8da6d0713e2092a27eee344cd54628b2c2065a0e77fff94df4ae00",
"sha256:1ef949b15a1f5f30651532a9b54edf3bd7c0b699a10931505fa2c80b2d395942",
"sha256:209927e65395feb449783943d62a3036982f871d7f4045fadb90b2d82b153ea8",
"sha256:25c77692ea8c0929d4ad400ea9c3dcbcc4936cee84e437e0ef80da58fa73d88a",
"sha256:28f27c64dd699b8b10f70da5f9320c1cffcaefca7dd76275b44571bd097f276c",
"sha256:355bd7d7ce5ff2917d217f0e8ddac568cb7403e1ce1639b35a924db7d13a39b6",
"sha256:4a0a33ada3f6f94f855f92460896ef08c798dcc5f17d9364d1735c5adc9d7e4a",
"sha256:4d3b6e66f32528bf43ca2297caca768280a8e068820b1c3dca0fcf9f03c7d6f1",
"sha256:5121fa96c79fc0ec81825091d0be5c16865f834f41b31da40b08ee60552f9961",
"sha256:57949756a3ce1f096fa2b00f812755f5ab2effeccedb19feeb7d0deafa3d1de7",
"sha256:586d931736912865c9790c60ca2db29e8dc4eace160d5a79fec3e58df79a9386",
"sha256:5ae532b93cf9ce5a2a549b74a2c35e3b690b171ece9358519b3039c7b84c887e",
"sha256:5dab393ab96b2ce4012823b2f2ed4ee907150424d2f02b97bd6f8dd8f17cc866",
"sha256:5ebc13451246de82f130e8ee7e723e8d7ae1827f14b7b0218867667b1b12c88d",
"sha256:68a149a0482d0bc697aac702ec6efb9d380e0afebf9484db5b7e634146528371",
"sha256:6db7ded10b82592c472eeeba34b9f12d7b0ab1e2dcad12f081b08ebdea78d7d6",
"sha256:6e545908bcc2ae28e5b190ce3170f92d0438cf26a82b269611390114de0106eb",
"sha256:6f328a3faaf81a2546a3022b3dfc137cc6d50d81082dbc0c94d1678943f05df3",
"sha256:706e2dea3de33b0d8884c4d35ecd5911b4ff04d0697c4138096666ce983671a6",
"sha256:80c3d1ce8820dd819d1c9d6b63b6f445148480a831173b572a9174a55e7abd47",
"sha256:8111b61eee12d7af5c58f82f2c97c2664677a05df9225ef5cbc2f25398c8c454",
"sha256:9713578f187fb1c4d00ac554fe1edcc6b3ddd62f5d4eb578b81261115802df8e",
"sha256:9c0669ba9aebad540fb05a33beb7e659ea6e5ca35833fc5229c20f057db760e8",
"sha256:9e9cfe55dc7ac2aa47e0fd3285ff829685f96803197042c9d2f0fb44e4b39b2c",
"sha256:a22daaf30037b8e59d6968c76fe0f7ff062c976c7a026e92fbefc4c4bf3fc5a4",
"sha256:a25b84e10018875a0f294a7649d07c43e8bc3e6a821714e39e5cd607a36386d7",
"sha256:a71138366d57901597bfcc52af7f076ab61c046f409c7b429011cd68de8f9fe6",
"sha256:b4efde5524579a9ce0459ca35a57a48ca878a4973514b8bb88cb80d7c9d34c85",
"sha256:b78af4d42985ab3143d9882d0006f48d12f1bc4ba88e78f23762777c3ee64571",
"sha256:bb2987eb3af9bcf46019be39b82c120c3d35639a95bc4ee2d08f36ecdf469345",
"sha256:c03ce53690fe492845e14f4ab7e67d5a429a06db99b226b5c7caa23081c1e2bb",
"sha256:c59b9280284b791377b3524c8e39ca7b74ae2881ba1a6c51b36f4f1bb94cee49",
"sha256:d18b4c8cacbb141979bb44355ee5813dd4d307e9d79b3a36d66eca7e0a203df8",
"sha256:d1e5563e3b7f844dbc48d709c9e4a75647e11d0387cc1fa0c861d3e9d34bc844",
"sha256:d22c897b65b1408509099f1c3334bd3704f5e4eb7c0486c57d0e212f71cb8f54",
"sha256:dbec0a3a154dbf2eb85b38abaddf24964fa1c059ee0a4ad55d6f39211b1a4bca",
"sha256:ed123037896a8db6709b8ad5acc0ed435453726ea0b63361d12de369624c2ab5",
"sha256:f3614dabd2cc8741850597b418bcf644d4f60e73615906c3acc407b78ff720b3",
"sha256:f9d632ce9fd485119c968ec6a7a343de698c5e014d17602ae2f110f1b05925ed",
"sha256:fb62996c61eeff56b59ab8abfcaa0859ec2223392c03d6085048b576b567459b"
],
"version": "==1.27.2"
},
"invoke": {
"hashes": [
"sha256:87b3ef9d72a1667e104f89b159eaf8a514dbf2f3576885b2bbdefe74c3fb2132",
"sha256:93e12876d88130c8e0d7fd6618dd5387d6b36da55ad541481dfa5e001656f134",
"sha256:de3f23bfe669e3db1085789fd859eb8ca8e0c5d9c20811e2407fa042e8a5e15d"
],
"version": "==1.4.1"
},
"lxml": {
"hashes": [
"sha256:06d4e0bbb1d62e38ae6118406d7cdb4693a3fa34ee3762238bcb96c9e36a93cd",
"sha256:0701f7965903a1c3f6f09328c1278ac0eee8f56f244e66af79cb224b7ef3801c",
"sha256:1f2c4ec372bf1c4a2c7e4bb20845e8bcf8050365189d86806bad1e3ae473d081",
"sha256:4235bc124fdcf611d02047d7034164897ade13046bda967768836629bc62784f",
"sha256:5828c7f3e615f3975d48f40d4fe66e8a7b25f16b5e5705ffe1d22e43fb1f6261",
"sha256:585c0869f75577ac7a8ff38d08f7aac9033da2c41c11352ebf86a04652758b7a",
"sha256:5d467ce9c5d35b3bcc7172c06320dddb275fea6ac2037f72f0a4d7472035cea9",
"sha256:63dbc21efd7e822c11d5ddbedbbb08cd11a41e0032e382a0fd59b0b08e405a3a",
"sha256:7bc1b221e7867f2e7ff1933165c0cec7153dce93d0cdba6554b42a8beb687bdb",
"sha256:8620ce80f50d023d414183bf90cc2576c2837b88e00bea3f33ad2630133bbb60",
"sha256:8a0ebda56ebca1a83eb2d1ac266649b80af8dd4b4a3502b2c1e09ac2f88fe128",
"sha256:90ed0e36455a81b25b7034038e40880189169c308a3df360861ad74da7b68c1a",
"sha256:95e67224815ef86924fbc2b71a9dbd1f7262384bca4bc4793645794ac4200717",
"sha256:afdb34b715daf814d1abea0317b6d672476b498472f1e5aacbadc34ebbc26e89",
"sha256:b4b2c63cc7963aedd08a5f5a454c9f67251b1ac9e22fd9d72836206c42dc2a72",
"sha256:d068f55bda3c2c3fcaec24bd083d9e2eede32c583faf084d6e4b9daaea77dde8",
"sha256:d5b3c4b7edd2e770375a01139be11307f04341ec709cf724e0f26ebb1eef12c3",
"sha256:deadf4df349d1dcd7b2853a2c8796593cc346600726eff680ed8ed11812382a7",
"sha256:df533af6f88080419c5a604d0d63b2c33b1c0c4409aba7d0cb6de305147ea8c8",
"sha256:e4aa948eb15018a657702fee0b9db47e908491c64d36b4a90f59a64741516e77",
"sha256:e5d842c73e4ef6ed8c1bd77806bf84a7cb535f9c0cf9b2c74d02ebda310070e1",
"sha256:ebec08091a22c2be870890913bdadd86fcd8e9f0f22bcb398abd3af914690c15",
"sha256:edc15fcfd77395e24543be48871c251f38132bb834d9fdfdad756adb6ea37679",
"sha256:f2b74784ed7e0bc2d02bd53e48ad6ba523c9b36c194260b7a5045071abbb1012",
"sha256:fa071559f14bd1e92077b1b5f6c22cf09756c6de7139370249eb372854ce51e6",
"sha256:fd52e796fee7171c4361d441796b64df1acfceb51f29e545e812f16d023c4bbc",
"sha256:fe976a0f1ef09b3638778024ab9fb8cde3118f203364212c198f71341c0715ca"
],
"version": "==4.5.0"
},
"mako": {
"hashes": [
"sha256:3139c5d64aa5d175dbafb95027057128b5fbd05a40c53999f3905ceb53366d9d",
"sha256:8e8b53c71c7e59f3de716b6832c4e401d903af574f6962edbbbf6ecc2a5fe6c9"
],
"version": "==1.1.2"
},
"markupsafe": {
"hashes": [
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
"sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
"sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
"sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
"sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
],
"version": "==1.1.1"
},
"netaddr": {
"hashes": [
"sha256:38aeec7cdd035081d3a4c306394b19d677623bf76fa0913f6695127c7753aefd",
"sha256:56b3558bd71f3f6999e4c52e349f38660e54a7a8a9943335f73dfc96883e08ca"
],
"version": "==0.7.19"
},
"paramiko": {
"hashes": [
"sha256:920492895db8013f6cc0179293147f830b8c7b21fdfc839b6bad760c27459d9f",
"sha256:9c980875fa4d2cb751604664e9a2d0f69096643f5be4db1b99599fe114a97b2f"
],
"version": "==2.7.1"
},
"pillow": {
"hashes": [
"sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be",
"sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946",
"sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837",
"sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f",
"sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00",
"sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d",
"sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533",
"sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a",
"sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358",
"sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda",
"sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435",
"sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2",
"sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313",
"sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff",
"sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317",
"sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2",
"sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614",
"sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0",
"sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386",
"sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9",
"sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636",
"sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"
],
"version": "==7.0.0"
},
"pycparser": {
"hashes": [
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
],
"version": "==2.20"
},
"pynacl": {
"hashes": [
"sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255",
"sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c",
"sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e",
"sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae",
"sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621",
"sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56",
"sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39",
"sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310",
"sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1",
"sha256:53126cd91356342dcae7e209f840212a58dcf1177ad52c1d938d428eebc9fee5",
"sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a",
"sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786",
"sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b",
"sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b",
"sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f",
"sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20",
"sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415",
"sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715",
"sha256:bf459128feb543cfca16a95f8da31e2e65e4c5257d2f3dfa8c0c1031139c9c92",
"sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1",
"sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"
],
"version": "==1.3.0"
},
"pyproj": {
"hashes": [
"sha256:0d8196a5ac75fee2cf71c21066b3344427abfa8ad69b536d3404d5c7c9c0b886",
"sha256:12e378a0a21c73f96177f6cf64520f17e6b7aa02fc9cb27bd5c2d5b06ce170af",
"sha256:17738836128704d8f80b771572d77b8733841f0cb0ca42620549236ea62c4663",
"sha256:1a39175944710b225fd1943cb3b8ea0c8e059d3016360022ca10bbb7a6bfc9ae",
"sha256:2566bffb5395c9fbdb02077a0bc3e3ed0b2e4e3cadf65019e3139a8dfe27dd1d",
"sha256:3f43277f21ddaabed93b9885a4e494b785dca56e31fd37a935519d99b07807f0",
"sha256:424304beca6e0b0bc12aa46fc6d14a481ea47b1a4edec4854bb281656de38948",
"sha256:48128d794c8f52fcff2433a481e3aa2ccb0e0b3ccd51d3ad7cc10cc488c3f547",
"sha256:4a16b650722982cddedd45dfc36435b96e0ba83a2aebd4a4c247e5a68c852442",
"sha256:5161f1b5ece8a5263b64d97a32fbc473a4c6fdca5c95478e58e519ef1e97528e",
"sha256:6839ce14635ebfb01c67e456148f4f1fa04b03ef9645551b89d36593f2a3e57d",
"sha256:80e9f85ab81da75289308f23a62e1426a38411a07b0da738958d65ae8cc6c59c",
"sha256:881b44e94c781d02ecf1d9314fc7f44c09e6d54a8eac281869365999ac4db7a1",
"sha256:977542d2f8cf2981cf3ad72cedfebcd6ac56977c7aa830d9b49fa7888b56e83d",
"sha256:9bba6cbff7e23bb6d9062786d516602681b4414e9e423c138a7360e4d2a193e8",
"sha256:9bf64bba03ddc534ed3c6271ba8f9d31040f40cf8e9e7e458b6b1524a6f59082",
"sha256:9c712ceaa01488ebe6e357e1dfa2434c2304aad8a810e5d4c3d2abe21def6d58",
"sha256:b7da17e5a5c6039f85843e88c2f1ca8606d1a4cc13a87e7b68b9f51a54ef201a",
"sha256:bcdf81b3f13d2cc0354a4c3f7a567b71fcf6fe8098e519aaaee8e61f05c9de10",
"sha256:bebd3f987b7196e9d2ccfe55911b0c76ba9ce309bcabfb629ef205cbaaad37c5",
"sha256:c244e923073cd0bab74ba861ba31724aab90efda35b47a9676603c1a8e80b3ba",
"sha256:dacb94a9d570f4d9fc9369a22d44d7b3071cfe4d57d0ff2f57abd7ef6127fe41"
],
"version": "==2.6.0"
},
"pyyaml": {
"hashes": [
"sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
"sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
"sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
"sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
"sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
"sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
"sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
"sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
"sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
"sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
"sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
],
"version": "==5.3.1"
},
"six": {
"hashes": [
"sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
"sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
],
"version": "==1.14.0"
}
},
"develop": {
"appdirs": {
"hashes": [
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
],
"version": "==1.4.3"
},
"attrs": {
"hashes": [
"sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
"sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
],
"version": "==19.3.0"
},
"black": {
"hashes": [
"sha256:09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf",
"sha256:68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c"
],
"index": "pypi",
"version": "==19.3b0"
},
"cfgv": {
"hashes": [
"sha256:1ccf53320421aeeb915275a196e23b3b8ae87dea8ac6698b1638001d4a486d53",
"sha256:c8e8f552ffcc6194f4e18dd4f68d9aef0c0d58ae7e7be8c82bee3c5e9edfa513"
],
"version": "==3.1.0"
},
"click": {
"hashes": [
"sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
"sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
],
"version": "==7.1.1"
},
"distlib": {
"hashes": [
"sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"
],
"version": "==0.3.0"
},
"entrypoints": {
"hashes": [
"sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19",
"sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"
],
"version": "==0.3"
},
"filelock": {
"hashes": [
"sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",
"sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"
],
"version": "==3.0.12"
},
"flake8": {
"hashes": [
"sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb",
"sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"
],
"index": "pypi",
"version": "==3.7.9"
},
"grpcio": {
"hashes": [
"sha256:02aef8ef1a5ac5f0836b543e462eb421df6048a7974211a906148053b8055ea6",
"sha256:07f82aefb4a56c7e1e52b78afb77d446847d27120a838a1a0489260182096045",
"sha256:1cff47297ee614e7ef66243dc34a776883ab6da9ca129ea114a802c5e58af5c1",
"sha256:1ec8fc865d8da6d0713e2092a27eee344cd54628b2c2065a0e77fff94df4ae00",
"sha256:1ef949b15a1f5f30651532a9b54edf3bd7c0b699a10931505fa2c80b2d395942",
"sha256:209927e65395feb449783943d62a3036982f871d7f4045fadb90b2d82b153ea8",
"sha256:25c77692ea8c0929d4ad400ea9c3dcbcc4936cee84e437e0ef80da58fa73d88a",
"sha256:28f27c64dd699b8b10f70da5f9320c1cffcaefca7dd76275b44571bd097f276c",
"sha256:355bd7d7ce5ff2917d217f0e8ddac568cb7403e1ce1639b35a924db7d13a39b6",
"sha256:4a0a33ada3f6f94f855f92460896ef08c798dcc5f17d9364d1735c5adc9d7e4a",
"sha256:4d3b6e66f32528bf43ca2297caca768280a8e068820b1c3dca0fcf9f03c7d6f1",
"sha256:5121fa96c79fc0ec81825091d0be5c16865f834f41b31da40b08ee60552f9961",
"sha256:57949756a3ce1f096fa2b00f812755f5ab2effeccedb19feeb7d0deafa3d1de7",
"sha256:586d931736912865c9790c60ca2db29e8dc4eace160d5a79fec3e58df79a9386",
"sha256:5ae532b93cf9ce5a2a549b74a2c35e3b690b171ece9358519b3039c7b84c887e",
"sha256:5dab393ab96b2ce4012823b2f2ed4ee907150424d2f02b97bd6f8dd8f17cc866",
"sha256:5ebc13451246de82f130e8ee7e723e8d7ae1827f14b7b0218867667b1b12c88d",
"sha256:68a149a0482d0bc697aac702ec6efb9d380e0afebf9484db5b7e634146528371",
"sha256:6db7ded10b82592c472eeeba34b9f12d7b0ab1e2dcad12f081b08ebdea78d7d6",
"sha256:6e545908bcc2ae28e5b190ce3170f92d0438cf26a82b269611390114de0106eb",
"sha256:6f328a3faaf81a2546a3022b3dfc137cc6d50d81082dbc0c94d1678943f05df3",
"sha256:706e2dea3de33b0d8884c4d35ecd5911b4ff04d0697c4138096666ce983671a6",
"sha256:80c3d1ce8820dd819d1c9d6b63b6f445148480a831173b572a9174a55e7abd47",
"sha256:8111b61eee12d7af5c58f82f2c97c2664677a05df9225ef5cbc2f25398c8c454",
"sha256:9713578f187fb1c4d00ac554fe1edcc6b3ddd62f5d4eb578b81261115802df8e",
"sha256:9c0669ba9aebad540fb05a33beb7e659ea6e5ca35833fc5229c20f057db760e8",
"sha256:9e9cfe55dc7ac2aa47e0fd3285ff829685f96803197042c9d2f0fb44e4b39b2c",
"sha256:a22daaf30037b8e59d6968c76fe0f7ff062c976c7a026e92fbefc4c4bf3fc5a4",
"sha256:a25b84e10018875a0f294a7649d07c43e8bc3e6a821714e39e5cd607a36386d7",
"sha256:a71138366d57901597bfcc52af7f076ab61c046f409c7b429011cd68de8f9fe6",
"sha256:b4efde5524579a9ce0459ca35a57a48ca878a4973514b8bb88cb80d7c9d34c85",
"sha256:b78af4d42985ab3143d9882d0006f48d12f1bc4ba88e78f23762777c3ee64571",
"sha256:bb2987eb3af9bcf46019be39b82c120c3d35639a95bc4ee2d08f36ecdf469345",
"sha256:c03ce53690fe492845e14f4ab7e67d5a429a06db99b226b5c7caa23081c1e2bb",
"sha256:c59b9280284b791377b3524c8e39ca7b74ae2881ba1a6c51b36f4f1bb94cee49",
"sha256:d18b4c8cacbb141979bb44355ee5813dd4d307e9d79b3a36d66eca7e0a203df8",
"sha256:d1e5563e3b7f844dbc48d709c9e4a75647e11d0387cc1fa0c861d3e9d34bc844",
"sha256:d22c897b65b1408509099f1c3334bd3704f5e4eb7c0486c57d0e212f71cb8f54",
"sha256:dbec0a3a154dbf2eb85b38abaddf24964fa1c059ee0a4ad55d6f39211b1a4bca",
"sha256:ed123037896a8db6709b8ad5acc0ed435453726ea0b63361d12de369624c2ab5",
"sha256:f3614dabd2cc8741850597b418bcf644d4f60e73615906c3acc407b78ff720b3",
"sha256:f9d632ce9fd485119c968ec6a7a343de698c5e014d17602ae2f110f1b05925ed",
"sha256:fb62996c61eeff56b59ab8abfcaa0859ec2223392c03d6085048b576b567459b"
],
"version": "==1.27.2"
},
"grpcio-tools": {
"hashes": [
"sha256:00c5080cfb197ed20ecf0d0ff2d07f1fc9c42c724cad21c40ff2d048de5712b1",
"sha256:069826dd02ce1886444cf4519c4fe1b05ac9ef41491f26e97400640531db47f6",
"sha256:1266b577abe7c720fd16a83d0a4999a192e87c4a98fc9f97e0b99b106b3e155f",
"sha256:16dc3fad04fe18d50777c56af7b2d9b9984cd1cfc71184646eb431196d1645c6",
"sha256:1de5a273eaffeb3d126a63345e9e848ea7db740762f700eb8b5d84c5e3e7687d",
"sha256:2ca280af2cae1a014a238057bd3c0a254527569a6a9169a01c07f0590081d530",
"sha256:43a1573400527a23e4174d88604fde7a9d9a69bf9473c21936b7f409858f8ebb",
"sha256:4698c6b6a57f73b14d91a542c69ff33a2da8729691b7060a5d7f6383624d045e",
"sha256:520b7dafddd0f82cb7e4f6e9c6ba1049aa804d0e207870def9fe7f94d1e14090",
"sha256:57f8b9e2c7f55cd45f6dd930d6de61deb42d3eb7f9788137fbc7155cf724132a",
"sha256:59fbeb5bb9a7b94eb61642ac2cee1db5233b8094ca76fc56d4e0c6c20b5dd85f",
"sha256:5fd7efc2fd3370bd2c72dc58f31a407a5dff5498befa145da211b2e8c6a52c63",
"sha256:6016c07d6566e3109a3c032cf3861902d66501ecc08a5a84c47e43027302f367",
"sha256:627c91923df75091d8c4d244af38d5ab7ed8d786d480751d6c2b9267fbb92fe0",
"sha256:69c4a63919b9007e845d9f8980becd2f89d808a4a431ca32b9723ee37b521cb1",
"sha256:77e25c241e33b75612f2aa62985f746c6f6803ec4e452da508bb7f8d90a69db4",
"sha256:7a2d5fb558ac153a326e742ebfd7020eb781c43d3ffd920abd42b2e6c6fdfb37",
"sha256:7b54b283ec83190680903a9037376dc915e1f03852a2d574ba4d981b7a1fd3d0",
"sha256:845a51305af9fc7f9e2078edaec9a759153195f6cf1fbb12b1fa6f077e56b260",
"sha256:84724458c86ff9b14c29b49e321f34d80445b379f4cd4d0494c694b49b1d6f88",
"sha256:87e8ca2c2d2d3e09b2a2bed5d740d7b3e64028dafb7d6be543b77eec85590736",
"sha256:8e7738a4b93842bca1158cde81a3587c9b7111823e40a1ddf73292ca9d58e08b",
"sha256:915a695bc112517af48126ee0ecdb6aff05ed33f3eeef28f0d076f1f6b52ef5e",
"sha256:99961156a36aae4a402d6b14c1e7efde642794b3ddbf32c51db0cb3a199e8b11",
"sha256:9ba88c2d99bcaf7b9cb720925e3290d73b2367d238c5779363fd5598b2dc98c7",
"sha256:a140bf853edb2b5e8692fe94869e3e34077d7599170c113d07a58286c604f4fe",
"sha256:a14dc7a36c845991d908a7179502ca47bcba5ae1817c4426ce68cf2c97b20ad9",
"sha256:a3d2aec4b09c8e59fee8b0d1ed668d09e8c48b738f03f5d8401d7eb409111c47",
"sha256:a8f892378b0b02526635b806f59141abbb429d19bec56e869e04f396502c9651",
"sha256:aaa5ae26883c3d58d1a4323981f96b941fa09bb8f0f368d97c6225585280cf04",
"sha256:b56caecc16307b088a431a4038c3b3bb7d0e7f9988cbd0e9fa04ac937455ea38",
"sha256:bd7f59ff1252a3db8a143b13ea1c1e93d4b8cf4b852eb48b22ef1e6942f62a84",
"sha256:c1bb8f47d58e9f7c4825abfe01e6b85eda53c8b31d2267ca4cddf3c4d0829b80",
"sha256:d1a5e5fa47ba9557a7d3b31605631805adc66cdba9d95b5d10dfc52cca1fed53",
"sha256:dcbc06556f3713a9348c4fce02d05d91e678fc320fb2bcf0ddf8e4bb11d17867",
"sha256:e17b2e0936b04ced99769e26111e1e86ba81619d1b2691b1364f795e45560953",
"sha256:e6932518db389ede8bf06b4119bbd3e17f42d4626e72dec2b8955b20ec732cb6",
"sha256:ea4b3ad696d976d5eac74ec8df9a2c692113e455446ee38d5b3bd87f8e034fa6",
"sha256:ee50b0cf0d28748ef9f941894eb50fc464bd61b8e96aaf80c5056bea9b80d580",
"sha256:ef624b6134aef737b3daa4fb7e806cb8c5749efecd0b1fa9ce4f7e060c7a0221",
"sha256:f5450aa904e720f9c6407b59e96a8951ed6a95463f49444b6d2594b067d39588",
"sha256:f8514453411d72cc3cf7d481f2b6057e5b7436736d0cd39ee2b2f72088bbf497",
"sha256:fae91f30dc050a8d0b32d20dc700e6092f0bd2138d83e9570fff3f0372c1b27e"
],
"index": "pypi",
"version": "==1.27.2"
},
"identify": {
"hashes": [
"sha256:a7577a1f55cee1d21953a5cf11a3c839ab87f5ef909a4cba6cf52ed72b4c6059",
"sha256:ab246293e6585a1c6361a505b68d5b501a0409310932b7de2c2ead667b564d89"
],
"version": "==1.4.13"
},
"importlib-metadata": {
"hashes": [
"sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
"sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
],
"markers": "python_version < '3.8'",
"version": "==1.6.0"
},
"importlib-resources": {
"hashes": [
"sha256:4019b6a9082d8ada9def02bece4a76b131518866790d58fdda0b5f8c603b36c2",
"sha256:dd98ceeef3f5ad2ef4cc287b8586da4ebad15877f351e9688987ad663a0a29b8"
],
"markers": "python_version < '3.7'",
"version": "==1.4.0"
},
"isort": {
"hashes": [
"sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
"sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
],
"index": "pypi",
"version": "==4.3.21"
},
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
],
"version": "==0.6.1"
},
"mock": {
"hashes": [
"sha256:3f9b2c0196c60d21838f307f5825a7b86b678cedc58ab9e50a8988187b4d81e0",
"sha256:dd33eb70232b6118298d516bbcecd26704689c386594f0f3c4f13867b2c56f72"
],
"index": "pypi",
"version": "==4.0.2"
},
"more-itertools": {
"hashes": [
"sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
"sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
],
"version": "==8.2.0"
},
"nodeenv": {
"hashes": [
"sha256:5b2438f2e42af54ca968dd1b374d14a1194848955187b0e5e4be1f73813a5212"
],
"version": "==1.3.5"
},
"packaging": {
"hashes": [
"sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
"sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
],
"version": "==20.3"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
],
"version": "==0.13.1"
},
"pre-commit": {
"hashes": [
"sha256:487c675916e6f99d355ec5595ad77b325689d423ef4839db1ed2f02f639c9522",
"sha256:c0aa11bce04a7b46c5544723aedf4e81a4d5f64ad1205a30a9ea12d5e81969e1"
],
"index": "pypi",
"version": "==2.2.0"
},
"protobuf": {
"hashes": [
"sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab",
"sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f",
"sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a",
"sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0",
"sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4",
"sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2",
"sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee",
"sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07",
"sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151",
"sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a",
"sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f",
"sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7",
"sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956",
"sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306",
"sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961",
"sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481",
"sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a",
"sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"
],
"version": "==3.11.3"
},
"py": {
"hashes": [
"sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
"sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
],
"version": "==1.8.1"
},
"pycodestyle": {
"hashes": [
"sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56",
"sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"
],
"version": "==2.5.0"
},
"pyflakes": {
"hashes": [
"sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0",
"sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"
],
"version": "==2.1.1"
},
"pyparsing": {
"hashes": [
"sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
"sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
],
"version": "==2.4.6"
},
"pytest": {
"hashes": [
"sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172",
"sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"
],
"index": "pypi",
"version": "==5.4.1"
},
"pyyaml": {
"hashes": [
"sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
"sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
"sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
"sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
"sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
"sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
"sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
"sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
"sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
"sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
"sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
],
"version": "==5.3.1"
},
"six": {
"hashes": [
"sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
"sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
],
"version": "==1.14.0"
},
"toml": {
"hashes": [
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
],
"version": "==0.10.0"
},
"virtualenv": {
"hashes": [
"sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25",
"sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5"
],
"version": "==20.0.15"
},
"wcwidth": {
"hashes": [
"sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1",
"sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"
],
"version": "==0.1.9"
},
"zipp": {
"hashes": [
"sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
"sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
],
"markers": "python_version < '3.8'",
"version": "==3.1.0"
}
}
}

View file

@ -78,7 +78,7 @@ class DockerNode(CoreNode):
name: str = None, name: str = None,
nodedir: str = None, nodedir: str = None,
server: DistributedServer = None, server: DistributedServer = None,
image: str = None image: str = None,
) -> None: ) -> None:
""" """
Create a DockerNode instance. Create a DockerNode instance.
@ -209,9 +209,7 @@ class DockerNode(CoreNode):
if self.server is not None: if self.server is not None:
self.host_cmd(f"rm -f {temp.name}") self.host_cmd(f"rm -f {temp.name}")
os.unlink(temp.name) os.unlink(temp.name)
logging.debug( logging.debug("node(%s) added file: %s; mode: 0%o", self.name, filename, mode)
"node(%s) added file: %s; mode: 0%o", self.name, filename, mode
)
def nodefilecopy(self, filename: str, srcfilename: str, mode: int = None) -> None: def nodefilecopy(self, filename: str, srcfilename: str, mode: int = None) -> None:
""" """

1085
daemon/poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

49
daemon/pyproject.toml Normal file
View file

@ -0,0 +1,49 @@
[tool.poetry]
name = "core"
version = "6.6.0"
description = "CORE Common Open Research Emulator"
authors = ["Boeing Research and Technology"]
license = "BSD-2-Clause"
repository = "https://github.com/coreemu/core"
documentation = "https://coreemu.github.io/core/"
include = ["core/gui/data/**/*", "core/configservices/*/templates"]
[tool.poetry.dependencies]
python = "^3.6"
dataclasses = { version = "*", python = "3.6" }
fabric = "*"
grpcio = "1.27.2"
invoke = "*"
lxml = "*"
mako = "*"
netaddr = "*"
pillow = "*"
protobuf = "*"
pyproj = "*"
pyyaml = "*"
[tool.poetry.dev-dependencies]
black = "==19.3b0"
flake8 = "*"
grpcio-tools = "1.27.2"
isort = "*"
mock = "*"
pre-commit = "*"
pytest = "*"
[tool.isort]
skip_glob = "*_pb2*.py,doc,build"
multi_line_output = 3
include_trailing_comma = "True"
force_grid_wrap = 0
use_parentheses = "True"
line_length = 88
[tool.black]
line_length = 88
exclude = ".+_pb2.*.py|doc/|build/|__pycache__/"
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

View file

@ -1,19 +0,0 @@
bcrypt==3.1.7
cffi==1.14.0
cryptography==2.8
dataclasses==0.7; python_version == "3.6"
fabric==2.5.0
grpcio==1.27.2
invoke==1.4.1
lxml==4.5.0
Mako==1.1.1
MarkupSafe==1.1.1
netaddr==0.7.19
paramiko==2.7.1
Pillow==7.0.0
protobuf==3.11.3
pycparser==2.19
PyNaCl==1.3.0
pyproj==2.5.0
PyYAML==5.3
six==1.14.0

View file

@ -1,20 +1,9 @@
[aliases]
test=pytest
[isort]
skip_glob=*_pb2*.py,utm.py,doc,build
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=88
[flake8] [flake8]
ignore=E501,W503,E203 ignore=E501,W503,E203
max-line-length=88 max-line-length=88
max-complexity=26 max-complexity=26
select=B,C,E,F,W,T4 select=B,C,E,F,W,T4
exclude=*_pb2*.py,utm.py,doc,build exclude=*_pb2*.py,doc,build
[tool:pytest] [tool:pytest]
norecursedirs=distributed emane norecursedirs=distributed emane

View file

@ -1,60 +0,0 @@
"""
Defines how CORE will be built for installation.
"""
import glob
import os
from setuptools import find_packages, setup
_CORE_DIR = "/etc/core"
_MAN_DIR = "share/man/man1"
_EXAMPLES_DIR = "share/core"
def recursive_files(data_path, files_path):
all_files = []
for path, _directories, filenames in os.walk(files_path):
directory = os.path.join(data_path, path)
files = []
for filename in filenames:
files.append(os.path.join(path, filename))
all_files.append((directory, files))
return all_files
data_files = [
(_CORE_DIR, glob.glob("data/*")),
(_MAN_DIR, glob.glob("../man/**.1")),
]
data_files.extend(recursive_files(_EXAMPLES_DIR, "examples"))
setup(
name="core",
version="@PACKAGE_VERSION@",
packages=find_packages(),
install_requires=[
'dataclasses;python_version=="3.6"',
"fabric",
"grpcio",
"invoke",
"lxml",
"mako",
"netaddr",
"pillow",
"protobuf",
"pyproj",
"pyyaml",
],
tests_require=[
"pytest",
],
data_files=data_files,
scripts=glob.glob("scripts/*"),
include_package_data=True,
description="Python components of CORE",
url="https://github.com/coreemu/core",
author="Boeing Research & Technology",
license="BSD",
long_description="Python scripts and modules for building virtual emulated networks.",
)

View file

@ -5,102 +5,133 @@
## Overview ## Overview
This section will describe how to install CORE from source or from a pre-built package. CORE provides a script to help automate installing all required software
CORE has been vetted on Ubuntu 18 and CentOS 7.6. Other versions and distributions to build and run, including a python virtual environment to run it all in.
can work, assuming you can get the required packages and versions similar to those
noted below for the tested distributions.
> **NOTE:** iproute2 4.5+ is a requirement for bridge related commands The following tools will be leveraged during installation:
|Tool|Description|
|---|---|
|pip|used to install pipx|
|pipx|used to install standalone python tools (invoke, poetry)|
|invoke|used to run provided tasks (install, daemon, gui, tests, etc)|
|poetry|used to install the managed python virtual environment for running CORE|
## Required Hardware ## Required Hardware
Any computer capable of running Linux should be able to run CORE. Since the physical machine will be hosting numerous Any computer capable of running Linux should be able to run CORE. Since the physical machine will be hosting numerous
containers, as a general rule you should select a machine having as much RAM and CPU resources as possible. containers, as a general rule you should select a machine having as much RAM and CPU resources as possible.
## Operating System ## Supported Linux Distributions
CORE requires a Linux operating system because it uses namespacing provided by the kernel. It does not run on Plan is to support recent Ubuntu and CentOS LTS releases.
Windows or Mac OS X operating systems (unless it is running within a virtual machine guest.) The
technology that CORE currently uses is Linux network namespaces.
Ubuntu and CentOS Linux are the recommended distributions for running CORE. However, these distributions are Verified:
not strictly required. CORE will likely work on other flavors of Linux as well, assuming dependencies are met. * Ubuntu - 18.04, 20.04
* CentOS - 7.8, 8.0*
> **NOTE:** CORE Services determine what run on each node. You may require other software packages depending on the > **NOTE:** Ubuntu 20.04 requires installing legacy ebtables for WLAN
services you wish to use. For example, the HTTP service will require the apache2 package. > functionality
## Installed Files > **NOTE:** CentOS 8 does not provide legacy ebtables support, WLAN will not
> function properly
CORE files are installed to the following directories by default, when the installation prefix is **/usr**. > **NOTE:** CentOS 8 does not have the netem kernel mod available by default
Install Path | Description CentOS 8 Enabled netem:
-------------|------------ ```shell
/usr/bin/core-gui|GUI startup command sudo yum update
/usr/bin/coretk-gui|BETA Python GUI # restart into updated kernel
/usr/bin/core-daemon|Daemon startup command sudo yum install -y kernel-modules-extra
/usr/bin/{core-cleanup, coresendmsg, core-manage}|Misc. helper commands/scripts sudo modprobe sch_netem
/usr/lib/core|GUI files ```
/usr/lib/python{3.6+}/dist-packages/core|Python modules for daemon/scripts
/etc/core/|Daemon and log configuration files
~/.core/|User-specific GUI preferences and scenario files
/usr/share/core/|Example scripts and scenarios
/usr/share/man/man1/|Command man pages
/etc/init.d/core-daemon|SysV startup script for daemon
/usr/lib/systemd/system/core-daemon.service|Systemd startup script for daemon
## Automated Install ## Utility Requirements
There is a helper script in the root of the repository that can help automate * iproute2 4.5+ is a requirement for bridge related commands
the CORE installation. Some steps require commands be ran as sudo and you * ebtables not backed by nftables
will be prompted for a password. This should work on Ubuntu/CentOS and will
install system dependencies, python dependencies, and CORE. This will target ## Automated Installation
system installations of python 3.6.
> **NOTE:** installs OSPF MDR
> **NOTE:** sets up script files using the prefix provided
> **NOTE:** install a systemd service file to /lib/systemd/system/core-daemon.service
```shell ```shell
# clone CORE repo
git clone https://github.com/coreemu/core.git git clone https://github.com/coreemu/core.git
cd core cd core
# run install script
# script usage: install.sh [-d] [-v]
#
# -v enable verbose install
# -d enable developer install
# -p install prefix, defaults to /usr/local
./install.sh ./install.sh
``` ```
You can target newer system python versions using the **-v** flag. Assuming ## Manual Installation
these versions are actually available on your system.
> **NOTE:** install OSPF MDR by manual instructions below
```shell ```shell
# ubuntu 3.7 # clone CORE repo
./install.sh -v 3.7 git clone https://github.com/coreemu/core.git
# centos 3.7 cd core
./install.sh -v 37
# install python3 and venv support
# ubuntu
sudo apt install -y python3-pip python3-venv
# centos
sudo yum install -y python3-pip
# install system dependencies
# ubuntu
sudo apt install -y automake pkg-config gcc libev-dev ebtables iproute2 \
ethtool tk python3-tk
# centos
sudo yum install -y automake pkgconf-pkg-config gcc gcc-c++ libev-devel \
iptables-ebtables iproute python3-devel python3-tkinter tk ethtool \
make kernel-modules-extra
# install grpcio-tools
python3 -m pip install --user grpcio==1.27.2 grpcio-tools==1.27.2
# build core
./bootstrap.sh
# centos requires --prefix=/usr
./configure
make
sudo make install
# install pipx, may need to restart terminal after ensurepath
python3 -m pip install --user pipx
python3 -m pipx ensurepath
# install poetry
pipx install poetry
# install poetry virtual environment
cd daemon
poetry install --no-dev
cd ..
# install invoke to run helper tasks
pipx install invoke
# install core scripts leveraging poetry virtual environment
# centos requires --prefix=/usr
inv install-scripts
# optionally install systemd service file
# centos requires --prefix=/usr
inv install-service
``` ```
## Pre-Req Installing Python ## Manually Install OSPF MDR (Routing Support)
Python 3.6 is the minimum required python version. Newer versions can be used if available.
These steps are needed, since the system packages can not provide all the
dependencies needed by CORE.
### Ubuntu
```shell
sudo apt install python3.6
sudo apt install python3-pip
```
### CentOS
```shell
sudo yum install python36
sudo yum install python3-pip
```
### Dependencies
Install the current python dependencies.
```shell
sudo python3 -m pip install -r requirements.txt
```
## Pre-Req Installing OSPF MDR
Virtual networks generally require some form of routing in order to work (e.g. to automatically populate routing Virtual networks generally require some form of routing in order to work (e.g. to automatically populate routing
tables for routing packets from one subnet to another.) CORE builds OSPF routing protocol configurations by tables for routing packets from one subnet to another.) CORE builds OSPF routing protocol configurations by
@ -110,21 +141,14 @@ default when the blue router node type is used.
suite with a modified version of OSPFv3, optimized for use with mobile wireless networks. The **mdr** node type suite with a modified version of OSPFv3, optimized for use with mobile wireless networks. The **mdr** node type
(and the MDR service) requires this variant of Quagga. (and the MDR service) requires this variant of Quagga.
### Ubuntu
```shell ```shell
sudo apt install libtool gawk libreadline-dev # system dependencies
``` # ubuntu
sudo apt install -y libtool gawk libreadline-dev
# centos
sudo yum install -y libtool gawk readline-devel
### CentOS # build and install
```shell
sudo yum install libtool gawk readline-devel
```
### Build and Install
```shell
git clone https://github.com/USNavalResearchLaboratory/ospf-mdr git clone https://github.com/USNavalResearchLaboratory/ospf-mdr
cd ospf-mdr cd ospf-mdr
./bootstrap.sh ./bootstrap.sh
@ -135,168 +159,64 @@ make
sudo make install sudo make install
``` ```
Note that the configuration directory */usr/local/etc/quagga* shown for Quagga above could be */etc/quagga*, ## Manually Install EMANE
if you create a symbolic link from */etc/quagga/Quagga.conf -> /usr/local/etc/quagga/Quagga.conf* on the host.
The *quaggaboot.sh* script in a Linux network namespace will try and do this for you if needed.
If you try to run quagga after installing from source and get an error such as: EMANE can be installed from deb or RPM packages or from source. See the
[EMANE GitHub](https://github.com/adjacentlink/emane) for full details.
Here are quick instructions for installing all EMANE packages for Ubuntu 18.04:
```shell ```shell
error while loading shared libraries libzebra.so.0 # install dependencies
# ubuntu
sudo apt-get install libssl-dev libxml-libxml-perl libxml-simple-perl
wget https://adjacentlink.com/downloads/emane/emane-1.2.5-release-1.ubuntu-18_04.amd64.tar.gz
tar xzf emane-1.2.5-release-1.ubuntu-18_04.amd64.tar.gz
# install base emane packages
sudo dpkg -i emane-1.2.5-release-1/deb/ubuntu-18_04/amd64/emane*.deb
# install python3 bindings
sudo dpkg -i emane-1.2.5-release-1/deb/ubuntu-18_04/amd64/python3*.deb
``` ```
this is usually a sign that you have to run ```sudo ldconfig```` to refresh the cache file. ## Using Invoke Tasks
## Installing from Packages The invoke tool installed by way of pipx provides conveniences for running
CORE tasks to help ensure usage of the create python virtual environment.
The easiest way to install CORE is using the pre-built packages. The package managers on Ubuntu or CentOS
will help in automatically installing most dependencies, except for the python ones described previously.
You can obtain the CORE packages from [CORE Releases](https://github.com/coreemu/core/releases).
### Ubuntu
Ubuntu package defaults to using systemd for running as a service.
```shell ```shell
sudo apt install ./core_$VERSION_amd64.deb Available tasks:
cleanup run core-cleanup removing leftover core nodes, bridges, directories
cli run core-cli used to query and modify a running session
daemon start core-daemon
gui start core-pygui
install install core, poetry, scripts, service, and ospf mdr
install-scripts install core script files, modified to leverage virtual environment
install-service install systemd core service
test run core tests
test-emane run core emane tests
test-mock run core tests using mock to avoid running as sudo
uninstall uninstall core
``` ```
### CentOS Example running the core-daemon task from the root of the repo:
```shell
inv daemon
```
**NOTE: tkimg is not required for the core-gui, but if you get an error message about it you can install the package Some tasks are wrappers around command line tools and requires running
on CentOS <= 6, or build from source otherwise** them with a slight variation for compatibility. You can enter the
poetry shell to run the script natively.
```shell ```shell
yum install ./core_$VERSION_x86_64.rpm # running core-cli as a task requires all options to be provided
``` # within a string
inv cli "query session -i 1"
Disabling SELINUX:
# entering the poetry shell to use core-cli natively
```shell cd $REPO/daemon
# change the following in /etc/sysconfig/selinux poetry shell
SELINUX=disabled core-cli query session -i 1
# add the following to the kernel line in /etc/grub.conf # exit the shell
selinux=0 exit
```
Turn off firewalls:
```shell
systemctl disable firewalld
systemctl disable iptables.service
systemctl disable ip6tables.service
chkconfig iptables off
chkconfig ip6tables off
```
You need to reboot after making these changes, or flush the firewall using
```shell
iptables -F
ip6tables -F
```
## Installing from Source
Steps for building from cloned source code. Python 3.6 is the minimum required version
a newer version can be used below if available.
### Distro Requirements
System packages required to build from source.
#### Ubuntu
```shell
sudo apt install git automake pkg-config gcc libev-dev ebtables iproute2 \
python3.6 python3.6-dev python3-pip python3-tk tk libtk-img ethtool autoconf
```
#### CentOS
```shell
sudo yum install git automake pkgconf-pkg-config gcc gcc-c++ libev-devel iptables-ebtables iproute \
python36 python36-devel python3-pip python3-tkinter tk ethtool autoconf
```
### Clone Repository
Clone the CORE repository for building from source.
```shell
git clone https://github.com/coreemu/core.git
```
### Install grpcio-tools
Python module grpcio-tools is currently needed to generate gRPC protobuf code.
Specifically leveraging 1.27.2 to avoid compatibility issues with older versions
of pip pulling down binary files.
```shell
python3 -m pip install --only-binary ":all:" --user grpcio-tools
```
### Build and Install
```shell
./bootstrap.sh
./configure
make
sudo make install
```
## Building Documentation
Building documentation requires python-sphinx not noted above.
```shell
sudo apt install python3-sphinx
sudo yum install python3-sphinx
./bootstrap.sh
./configure
make doc
```
## Building Packages
Build package commands, DESTDIR is used to make install into and then for packaging by fpm.
**NOTE: clean the DESTDIR if re-using the same directory**
* Install [fpm](http://fpm.readthedocs.io/en/latest/installing.html)
```shell
./bootstrap.sh
./configure
make
mkdir /tmp/core-build
make fpm DESTDIR=/tmp/core-build
```
This will produce and RPM and Deb package for the currently configured python version.
## Running CORE
Start the CORE daemon.
```shell
# systemd
sudo systemctl daemon-reload
sudo systemctl start core-daemon
# sysv
sudo service core-daemon start
```
Run the GUI
```shell
# default gui
core-gui
# new beta gui
coretk-gui
``` ```

View file

@ -3,57 +3,6 @@
# exit on error # exit on error
set -e set -e
ubuntu_py=3.6
centos_py=36
reinstall=
function install_python_depencencies() {
sudo python3 -m pip install -r daemon/requirements.txt
}
function install_grpcio_tools() {
python3 -m pip install --only-binary ":all:" --user grpcio-tools
}
function install_ospf_mdr() {
rm -rf /tmp/ospf-mdr
git clone https://github.com/USNavalResearchLaboratory/ospf-mdr /tmp/ospf-mdr
cd /tmp/ospf-mdr
./bootstrap.sh
./configure --disable-doc --enable-user=root --enable-group=root --with-cflags=-ggdb \
--sysconfdir=/usr/local/etc/quagga --enable-vtysh \
--localstatedir=/var/run/quagga
make -j8
sudo make install
cd -
}
function build_core() {
./bootstrap.sh
./configure $1
make -j8
}
function install_core() {
sudo make install
}
function uninstall_core() {
sudo make uninstall
make clean
./bootstrap.sh clean
}
function install_dev_core() {
cd gui
sudo make install
cd -
cd netns
sudo make install
cd -
cd daemon
}
# detect os/ver for install type # detect os/ver for install type
os="" os=""
if [[ -f /etc/os-release ]]; then if [[ -f /etc/os-release ]]; then
@ -62,100 +11,47 @@ if [[ -f /etc/os-release ]]; then
fi fi
# parse arguments # parse arguments
while getopts "drv:" opt; do dev=""
verbose=""
prefix=""
while getopts "dvp:" opt; do
case ${opt} in case ${opt} in
d) d)
dev=1 dev="-d"
;; ;;
v) v)
ubuntu_py=${OPTARG} verbose="-v"
centos_py=${OPTARG}
;; ;;
r) p)
reinstall=1 prefix="-p ${OPTARG}"
;; ;;
\?) \?)
echo "script usage: $(basename $0) [-d] [-r] [-v python version]" >&2 echo "script usage: $(basename $0) [-d] [-v]" >&2
echo "" >&2
echo "-v enable verbose install" >&2
echo "-d enable developer install" >&2
echo "-p install prefix, defaults to /usr/local" >&2
exit 1 exit 1
;; ;;
esac esac
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
# check if we are reinstalling or installing
if [ -z "${reinstall}" ]; then
echo "installing CORE for ${os}" echo "installing CORE for ${os}"
case ${os} in case ${os} in
"ubuntu") "ubuntu")
echo "installing core system dependencies" sudo apt install -y python3-pip python3-venv
sudo apt install -y automake pkg-config gcc libev-dev ebtables iproute2 \
python${ubuntu_py} python${ubuntu_py}-dev python3-pip python3-tk tk libtk-img ethtool autoconf
install_grpcio_tools
echo "installing ospf-mdr system dependencies"
sudo apt install -y libtool gawk libreadline-dev
install_ospf_mdr
if [[ -z ${dev} ]]; then
echo "normal install"
install_python_depencencies
build_core
install_core
else
echo "dev install"
python3 -m pip install pipenv
build_core
install_dev_core
python3 -m pipenv sync --dev
python3 -m pipenv run pre-commit install
fi
;; ;;
"centos") "centos")
echo "installing core system dependencies" sudo yum install -y python3-pip
sudo yum install -y automake pkgconf-pkg-config gcc gcc-c++ libev-devel iptables-ebtables iproute \
python${centos_py} python${centos_py}-devel python3-pip python3-tkinter tk ethtool autoconf
install_grpcio_tools
echo "installing ospf-mdr system dependencies"
sudo yum install -y libtool gawk readline-devel
install_ospf_mdr
if [[ -z ${dev} ]]; then
echo "normal install"
install_python_depencencies
build_core --prefix=/usr
install_core
else
echo "dev install"
sudo python3 -m pip install pipenv
build_core --prefix=/usr
install_dev_core
sudo python3 -m pipenv sync --dev
python3 -m pipenv sync --dev
python3 -m pipenv run pre-commit install
fi
;; ;;
*) *)
echo "unknown OS ID ${os} cannot install" echo "unknown OS ID ${os} cannot install"
;; ;;
esac esac
else
branch=$(git symbolic-ref --short HEAD) python3 -m pip install --user pipx
echo "reinstalling CORE on ${os} with latest ${branch}" python3 -m pipx ensurepath
echo "uninstalling CORE" export PATH=$PATH:~/.local/bin
uninstall_core pipx install invoke
echo "pulling latest code" inv install ${dev} ${verbose} ${prefix}
git pull
echo "installing python dependencies"
install_python_depencencies
echo "building CORE"
case ${os} in
"ubuntu")
build_core
;;
"centos")
build_core --prefix=/usr
;;
*)
echo "unknown OS ID ${os} cannot reinstall"
;;
esac
echo "installing CORE"
install_core
fi

2
scripts/.gitignore vendored
View file

@ -1,2 +0,0 @@
core-daemon
core-daemon.service

View file

@ -1,31 +0,0 @@
# CORE
# (c)2011-2013 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Makefile for installing scripts.
#
CLEANFILES = core-daemon
DISTCLEANFILES = Makefile.in core-daemon.service core-daemon
EXTRA_DIST = core-daemon.in core-daemon.service.in
SUBDIRS =
# install startup scripts based on --with-startup=option configure option
# init.d (default), systemd
if WANT_INITD
startupdir = /etc/init.d
startup_SCRIPTS = core-daemon
endif
if WANT_SYSTEMD
startupdir = /usr/lib/systemd/system
startup_SCRIPTS = core-daemon.service
endif
# remove extra scripts and their directories if they are empty
uninstall-hook:
rmdir -p $(startupdir) || true

View file

@ -1,112 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: core-daemon
# Required-Start: $network $remote_fs
# Required-Stop: $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the core-daemon CORE daemon at boot time
# Description: Starts and stops the core-daemon CORE daemon used to
# provide network emulation services for the CORE GUI
# or scripts.
### END INIT INFO
#
# chkconfig: 35 90 03
# description: Starts and stops the CORE daemon \
# used to provide network emulation services.
#
# config: /etc/core/
NAME=`basename $0`
PIDFILE="@CORE_STATE_DIR@/run/$NAME.pid"
LOG="@CORE_STATE_DIR@/log/$NAME.log"
CMD="@bindir@/$NAME"
get_pid() {
cat "$PIDFILE"
}
is_alive() {
[ -f "$PIDFILE" ] && ps -p `get_pid` > /dev/null 2>&1
}
corestart() {
if is_alive; then
echo "$NAME already started"
else
echo "starting $NAME"
$CMD 2>&1 >> "$LOG" &
fi
echo $! > "$PIDFILE"
if ! is_alive; then
echo "unable to start $NAME, see $LOG"
exit 1
fi
}
corestop() {
if is_alive; then
echo -n "stopping $NAME.."
kill `get_pid`
for i in 1 2 3 4 5; do
sleep 1
if ! is_alive; then
break
fi
echo -n "."
done
echo
if is_alive; then
echo "not stopped; may still be shutting down"
exit 1
else
echo "stopped"
if [ -f "$PIDFILE" ]; then
rm -f "$PIDFILE"
fi
fi
else
echo "$NAME not running"
fi
}
corerestart() {
corestop
corestart
}
corestatus() {
if is_alive; then
echo "$NAME is running"
else
echo "$NAME is stopped"
exit 1
fi
}
case "$1" in
start)
corestart
;;
stop)
corestop
;;
restart)
corerestart
;;
force-reload)
corerestart
;;
status)
corestatus
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit $?

View file

@ -1,11 +0,0 @@
[Unit]
Description=Common Open Research Emulator Service
After=network.target
[Service]
Type=simple
ExecStart=@bindir@/core-daemon
TasksMax=infinity
[Install]
WantedBy=multi-user.target

399
tasks.py Normal file
View file

@ -0,0 +1,399 @@
import inspect
import itertools
import os
import sys
import threading
import time
from contextlib import contextmanager
from enum import Enum
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Optional
from invoke import task, Context
DAEMON_DIR: str = "daemon"
DEFAULT_PREFIX: str = "/usr/local"
class Progress:
cycles = itertools.cycle(["-", "/", "|", "\\"])
def __init__(self, verbose: bool) -> None:
self.verbose: bool = verbose
self.thread: Optional[threading.Thread] = None
self.running: bool = False
@contextmanager
def start(self, message: str) -> None:
if not self.verbose:
print(f"{message} ... ", end="")
self.running = True
self.thread = threading.Thread(target=self.run, daemon=True)
self.thread.start()
yield
self.stop()
def run(self) -> None:
while self.running:
sys.stdout.write(next(self.cycles))
sys.stdout.flush()
sys.stdout.write("\b")
time.sleep(0.1)
def stop(self) -> None:
if not self.verbose:
print("done")
if self.thread:
self.running = False
self.thread.join()
self.thread = None
class OsName(Enum):
UBUNTU = "ubuntu"
CENTOS = "centos"
class OsLike(Enum):
DEBIAN = "debian"
REDHAT = "rhel fedora"
class OsInfo:
def __init__(self, name: OsName, like: OsLike, version: float) -> None:
self.name: OsName = name
self.like: OsLike = like
self.version: float = version
def get_python(c: Context, warn: bool = False) -> str:
with c.cd(DAEMON_DIR):
r = c.run("poetry env info -p", warn=warn, hide=True)
if r.ok:
venv = r.stdout.strip()
return os.path.join(venv, "bin", "python")
else:
return ""
def get_pytest(c: Context) -> str:
with c.cd(DAEMON_DIR):
venv = c.run("poetry env info -p", hide=True).stdout.strip()
return os.path.join(venv, "bin", "pytest")
def get_os() -> OsInfo:
d = {}
with open("/etc/os-release", "r") as f:
for line in f.readlines():
line = line.strip()
if not line:
continue
key, value = line.split("=")
d[key] = value.strip("\"")
name_value = d["ID"]
like_value = d["ID_LIKE"]
version_value = d["VERSION_ID"]
try:
name = OsName(name_value)
like = OsLike(like_value)
version = float(version_value)
except ValueError:
print(
f"unsupported os({name_value}) like({like_value}) version({version_value}"
)
sys.exit(1)
return OsInfo(name, like, version)
def install_system(c: Context, os_info: OsInfo, hide: bool) -> None:
if os_info.like == OsLike.DEBIAN:
c.run(
"sudo apt install -y automake pkg-config gcc libev-dev ebtables "
"iproute2 ethtool tk python3-tk",
hide=hide
)
elif os_info.like == OsLike.REDHAT:
c.run(
"sudo yum install -y automake pkgconf-pkg-config gcc gcc-c++ "
"libev-devel iptables-ebtables iproute python3-devel python3-tkinter "
"tk ethtool make",
hide=hide
)
# centos 8+ does not support netem by default
if os_info.name == OsName.CENTOS and os_info.version >= 8:
c.run("sudo yum install -y kernel-modules-extra", hide=hide)
if not c.run("sudo modprobe sch_netem", warn=True, hide=hide):
print("\nERROR: you need to install the latest kernel")
print("run the following, restart, and try again")
print("sudo yum update")
sys.exit(1)
# attempt to setup legacy ebtables when an nftables based version is found
r = c.run("ebtables -V", hide=hide)
if "nf_tables" in r.stdout:
if not c.run(
"sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy",
warn=True,
hide=hide
):
print(
"\nWARNING: unable to setup ebtables-legacy, WLAN will not work"
)
def install_grpcio(c: Context, hide: bool) -> None:
c.run(
"python3 -m pip install --user grpcio==1.27.2 grpcio-tools==1.27.2",
hide=hide,
)
def build_core(c: Context, hide: bool, prefix: str = DEFAULT_PREFIX) -> None:
c.run("./bootstrap.sh", hide=hide)
c.run(f"./configure --prefix={prefix}", hide=hide)
c.run("make -j$(nproc)", hide=hide)
def install_core(c: Context, hide: bool) -> None:
c.run("sudo make install", hide=hide)
def install_poetry(c: Context, dev: bool, hide: bool) -> None:
c.run("pipx install poetry", hide=hide)
args = "" if dev else "--no-dev"
with c.cd(DAEMON_DIR):
c.run(f"poetry install {args}", hide=hide)
if dev:
c.run("poetry run pre-commit install", hide=hide)
def install_ospf_mdr(c: Context, os_info: OsInfo, hide: bool) -> None:
if c.run("which zebra", warn=True, hide=hide):
print("\nquagga already installed, skipping ospf mdr")
return
if os_info.like == OsLike.DEBIAN:
c.run("sudo apt install -y libtool gawk libreadline-dev git", hide=hide)
elif os_info.like == OsLike.REDHAT:
c.run("sudo yum install -y libtool gawk readline-devel git", hide=hide)
clone_dir = "/tmp/ospf-mdr"
c.run(
f"git clone https://github.com/USNavalResearchLaboratory/ospf-mdr {clone_dir}",
hide=hide
)
with c.cd(clone_dir):
c.run("./bootstrap.sh", hide=hide)
c.run(
"./configure --disable-doc --enable-user=root --enable-group=root "
"--with-cflags=-ggdb --sysconfdir=/usr/local/etc/quagga --enable-vtysh "
"--localstatedir=/var/run/quagga",
hide=hide
)
c.run("make -j$(nproc)", hide=hide)
c.run("sudo make install", hide=hide)
@task
def install_service(c, verbose=False, prefix=DEFAULT_PREFIX):
"""
install systemd core service
"""
hide = not verbose
bin_dir = Path(prefix).joinpath("bin")
systemd_dir = Path("/lib/systemd/system/")
service_file = systemd_dir.joinpath("core-daemon.service")
if systemd_dir.exists():
service_data = inspect.cleandoc(f"""
[Unit]
Description=Common Open Research Emulator Service
After=network.target
[Service]
Type=simple
ExecStart={bin_dir}/core-daemon
TasksMax=infinity
[Install]
WantedBy=multi-user.target
""")
temp = NamedTemporaryFile("w", delete=False)
temp.write(service_data)
temp.close()
c.run(f"sudo cp {temp.name} {service_file}", hide=hide)
else:
print(f"ERROR: systemd service path not found: {systemd_dir}")
@task
def install_scripts(c, verbose=False, prefix=DEFAULT_PREFIX):
"""
install core script files, modified to leverage virtual environment
"""
hide = not verbose
python = get_python(c)
bin_dir = Path(prefix).joinpath("bin")
for script in Path("daemon/scripts").iterdir():
dest = bin_dir.joinpath(script.name)
with open(script, "r") as f:
lines = f.readlines()
first = lines[0].strip()
# modify python scripts to point to virtual environment
if first == "#!/usr/bin/env python3":
lines[0] = f"#!{python}\n"
temp = NamedTemporaryFile("w", delete=False)
for line in lines:
temp.write(line)
temp.close()
c.run(f"sudo cp {temp.name} {dest}", hide=hide)
c.run(f"sudo chmod 755 {dest}", hide=hide)
os.unlink(temp.name)
# copy normal links
else:
c.run(f"sudo cp {script} {dest}", hide=hide)
# install core configuration file
config_dir = "/etc/core"
c.run(f"sudo mkdir -p {config_dir}", hide=hide)
c.run(f"sudo cp -n daemon/data/core.conf {config_dir}", hide=hide)
c.run(f"sudo cp -n daemon/data/logging.conf {config_dir}", hide=hide)
@task
def install(c, dev=False, verbose=False, prefix=DEFAULT_PREFIX):
"""
install core, poetry, scripts, service, and ospf mdr
"""
c.run("sudo -v", hide=True)
print(f"installing core with prefix: {prefix}")
p = Progress(verbose)
hide = not verbose
os_info = get_os()
with p.start("installing system dependencies"):
install_system(c, os_info, hide)
with p.start("installing system grpcio-tools"):
install_grpcio(c, hide)
with p.start("building core"):
build_core(c, hide, prefix)
with p.start("installing vcmd/gui"):
install_core(c, hide)
with p.start("installing poetry virtual environment"):
install_poetry(c, dev, hide)
with p.start("installing scripts and /etc/core"):
install_scripts(c, hide, prefix)
with p.start("installing systemd service"):
install_service(c, hide, prefix)
with p.start("installing ospf mdr"):
install_ospf_mdr(c, os_info, hide)
print("\nyou may need to open a new terminal to leverage invoke for running core")
@task
def uninstall(c, dev=False, verbose=False, prefix=DEFAULT_PREFIX):
"""
uninstall core
"""
hide = not verbose
p = Progress(verbose)
c.run("sudo -v", hide=True)
with p.start("uninstalling core"):
c.run("sudo make uninstall", hide=hide)
with p.start("cleaning build directory"):
c.run("make clean", hide=hide)
c.run("./bootstrap.sh clean", hide=hide)
python = get_python(c, warn=True)
if python:
with c.cd(DAEMON_DIR):
if dev:
with p.start("uninstalling pre-commit"):
c.run("poetry run pre-commit uninstall", hide=hide)
with p.start("uninstalling poetry virtual environment"):
c.run(f"poetry env remove {python}", hide=hide)
# remove installed files
bin_dir = Path(prefix).joinpath("bin")
with p.start("uninstalling script files"):
for script in Path("daemon/scripts").iterdir():
dest = bin_dir.joinpath(script.name)
c.run(f"sudo rm -f {dest}", hide=hide)
# install service
systemd_dir = Path("/lib/systemd/system/")
service_name = "core-daemon.service"
service_file = systemd_dir.joinpath(service_name)
if service_file.exists():
with p.start(f"uninstalling service {service_file}"):
c.run(f"sudo systemctl disable {service_name}", hide=hide)
c.run(f"sudo rm -f {service_file}", hide=hide)
@task
def daemon(c):
"""
start core-daemon
"""
python = get_python(c)
with c.cd(DAEMON_DIR):
c.run(
f"sudo {python} scripts/core-daemon "
"-f data/core.conf -l data/logging.conf",
pty=True
)
@task
def gui(c):
"""
start core-pygui
"""
with c.cd(DAEMON_DIR):
c.run("poetry run scripts/core-pygui", pty=True)
@task
def cli(c, args):
"""
run core-cli used to query and modify a running session
"""
with c.cd(DAEMON_DIR):
c.run(f"poetry run scripts/core-cli {args}", pty=True)
@task
def cleanup(c):
"""
run core-cleanup removing leftover core nodes, bridges, directories
"""
print("running core-cleanup...")
c.run(f"sudo daemon/scripts/core-cleanup", pty=True)
@task
def test(c):
"""
run core tests
"""
pytest = get_pytest(c)
with c.cd(DAEMON_DIR):
c.run(f"sudo {pytest} -v --lf -x tests", pty=True)
@task
def test_mock(c):
"""
run core tests using mock to avoid running as sudo
"""
with c.cd(DAEMON_DIR):
c.run("poetry run pytest -v --mock --lf -x tests", pty=True)
@task
def test_emane(c):
"""
run core emane tests
"""
pytest = get_pytest(c)
with c.cd(DAEMON_DIR):
c.run(f"{pytest} -v --lf -x tests/emane", pty=True)