diff --git a/Makefile.am b/Makefile.am index ff31a5a4..c51c3707 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,15 +44,6 @@ DISTCLEANFILES = aclocal.m4 \ MAINTAINERCLEANFILES = .version \ .version.date - -if PYTHON3 -PYTHON_DEB_DEP = python3 >= 3.6 -PYTHON_RPM_DEP = python3 >= 3.6 -else -PYTHON_DEB_DEP = python (>= 2.7), python (<< 3.0) -PYTHON_RPM_DEP = python >= 2.7, python < 3.0 -endif - define fpm-rpm = fpm -s dir -t rpm -n core \ -m "$(PACKAGE_MAINTAINERS)" \ @@ -74,7 +65,7 @@ fpm -s dir -t rpm -n core \ -d "iproute" \ -d "libev" \ -d "net-tools" \ - -d "$(PYTHON_RPM_DEP)" \ + -d "python3 >= 3.6" \ -C $(DESTDIR) endef @@ -101,7 +92,7 @@ fpm -s dir -t deb -n core \ -d "ebtables" \ -d "iproute2" \ -d "libev4" \ - -d "$(PYTHON_DEB_DEP)" \ + -d "python3 >= 3.6" \ -C $(DESTDIR) endef diff --git a/configure.ac b/configure.ac index fec902a3..5d04356e 100644 --- a/configure.ac +++ b/configure.ac @@ -55,12 +55,6 @@ else want_python=no fi -AC_ARG_ENABLE([python3], - [AS_HELP_STRING([--enable-python3], - [sets python3 flag for building packages])], - [enable_python3=yes], [enable_python3=no]) -AM_CONDITIONAL([PYTHON3], [test "x$enable_python3" == "xyes"]) - AC_ARG_ENABLE([daemon], [AS_HELP_STRING([--enable-daemon[=ARG]], [build and install the daemon with Python modules @@ -116,7 +110,7 @@ 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) + AM_PATH_PYTHON(3.6) AS_IF([$PYTHON -m grpc_tools.protoc -h &> /dev/null], [], [AC_MSG_ERROR([please install python grpcio-tools])]) AC_CHECK_PROG(brctl_path, brctl, $as_dir, no, $SEARCHPATH) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index a6503cc0..80483387 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -14,8 +14,6 @@ if WANT_DOCS DOCS = doc endif -PYTHONLIBDIR=$(subst site-packages,dist-packages,$(pythondir)) - SUBDIRS = proto $(DOCS) SCRIPT_FILES := $(notdir $(wildcard scripts/*)) @@ -31,7 +29,7 @@ install-exec-hook: $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ --root=/$(DESTDIR) \ --prefix=$(prefix) \ - --install-lib=$(PYTHONLIBDIR) \ + --install-lib=$(pythondir) \ --single-version-externally-managed # Python package uninstall @@ -40,8 +38,8 @@ uninstall-hook: rm -rf $(DESTDIR)/$(datadir)/core rm -f $(addprefix $(DESTDIR)/$(datarootdir)/man/man1/, $(MAN_FILES)) rm -f $(addprefix $(DESTDIR)/$(bindir)/,$(SCRIPT_FILES)) - rm -rf $(DESTDIR)/$(PYTHONLIBDIR)/core-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info - rm -rf $(DESTDIR)/$(PYTHONLIBDIR)/core + rm -rf $(DESTDIR)/$(pythondir)/core-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + rm -rf $(DESTDIR)/$(pythondir)/core # Python package cleanup clean-local: diff --git a/daemon/Pipfile b/daemon/Pipfile index a1e33a29..a689f4dc 100644 --- a/daemon/Pipfile +++ b/daemon/Pipfile @@ -4,7 +4,7 @@ url = "https://pypi.org/simple" verify_ssl = true [scripts] -core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf --grpc" +core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf" test = "pytest -v tests" test_emane = "pytest -v tests/emane" diff --git a/daemon/Pipfile.lock b/daemon/Pipfile.lock index 73400b8b..4bdaea3f 100644 --- a/daemon/Pipfile.lock +++ b/daemon/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d702e6eed5a1362bf261543572bbffd2e8a87140b8d8cb07b99fb0d25220a2b5" + "sha256": "6195c89ec6e2e449fcbd7f3fa41cbab79c02d952984a913e0f80114e1904bf11" }, "pipfile-spec": 6, "requires": {}, @@ -14,13 +14,6 @@ ] }, "default": { - "asn1crypto": { - "hashes": [ - "sha256:0b199f211ae690df3db4fd6c1c4ff976497fb1da689193e368eedbadc53d9292", - "sha256:bca90060bd995c3f62c4433168eab407e44bdbdb567b3f3a396a676c1a4c4a3f" - ], - "version": "==1.0.1" - }, "bcrypt": { "hashes": [ "sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89", @@ -44,43 +37,40 @@ }, "cffi": { "hashes": [ - "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774", - "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d", - "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90", - "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b", - "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63", - "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45", - "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25", - "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3", - "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b", - "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647", - "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016", - "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4", - "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb", - "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753", - "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7", - "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9", - "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f", - "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8", - "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f", - "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc", - "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42", - "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3", - "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909", - "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45", - "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d", - "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512", - "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff", - "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201" + "sha256:08f99e8b38d5134d504aa7e486af8e4fde66a2f388bbecc270cdd1e00fa09ff8", + "sha256:1112d2fc92a867a6103bce6740a549e74b1d320cf28875609f6e93857eee4f2d", + "sha256:1b9ab50c74e075bd2ae489853c5f7f592160b379df53b7f72befcbe145475a36", + "sha256:24eff2997436b6156c2f30bed215c782b1d8fd8c6a704206053c79af95962e45", + "sha256:2eff642fbc9877a6449026ad66bf37c73bf4232505fb557168ba5c502f95999b", + "sha256:362e896cea1249ed5c2a81cf6477fabd9e1a5088aa7ea08358a4c6b0998294d2", + "sha256:40eddb3589f382cb950f2dcf1c39c9b8d7bd5af20665ce273815b0d24635008b", + "sha256:5ed40760976f6b8613d4a0db5e423673ca162d4ed6c9ed92d1f4e58a47ee01b5", + "sha256:632c6112c1e914c486f06cfe3f0cc507f44aa1e00ebf732cedb5719e6aa0466a", + "sha256:64d84f0145e181f4e6cc942088603c8db3ae23485c37eeda71cb3900b5e67cb4", + "sha256:6cb4edcf87d0e7f5bdc7e5c1a0756fbb37081b2181293c5fdf203347df1cd2a2", + "sha256:6f19c9df4785305669335b934c852133faed913c0faa63056248168966f7a7d5", + "sha256:719537b4c5cd5218f0f47826dd705fb7a21d83824920088c4214794457113f3f", + "sha256:7b0e337a70e58f1a36fb483fd63880c9e74f1db5c532b4082bceac83df1523fa", + "sha256:853376efeeb8a4ae49a737d5d30f5db8cdf01d9319695719c4af126488df5a6a", + "sha256:85bbf77ffd12985d76a69d2feb449e35ecdcb4fc54a5f087d2bd54158ae5bb0c", + "sha256:8978115c6f0b0ce5880bc21c967c65058be8a15f1b81aa5fdbdcbea0e03952d1", + "sha256:8f7eec920bc83692231d7306b3e311586c2e340db2dc734c43c37fbf9c981d24", + "sha256:8fe230f612c18af1df6f348d02d682fe2c28ca0a6c3856c99599cdacae7cf226", + "sha256:92068ebc494b5f9826b822cec6569f1f47b9a446a3fef477e1d11d7fac9ea895", + "sha256:b57e1c8bcdd7340e9c9d09613b5e7fdd0c600be142f04e2cc1cc8cb7c0b43529", + "sha256:ba956c9b44646bc1852db715b4a252e52a8f5a4009b57f1dac48ba3203a7bde1", + "sha256:ca42034c11eb447497ea0e7b855d87ccc2aebc1e253c22e7d276b8599c112a27", + "sha256:dc9b2003e9a62bbe0c84a04c61b0329e86fccd85134a78d7aca373bbbf788165", + "sha256:dd308802beb4b2961af8f037becbdf01a1e85009fdfc14088614c1b3c383fae5", + "sha256:e77cd105b19b8cd721d101687fcf665fd1553eb7b57556a1ef0d453b6fc42faa", + "sha256:f56dff1bd81022f1c980754ec721fb8da56192b026f17f0f99b965da5ab4fbd2", + "sha256:fa4cc13c03ea1d0d37ce8528e0ecc988d2365e8ac64d8d86cafab4038cb4ce89", + "sha256:fa8cf1cb974a9f5911d2a0303f6adc40625c05578d8e7ff5d313e1e27850bd59", + "sha256:fb003019f06d5fc0aa4738492ad8df1fa343b8a37cbcf634018ad78575d185df", + "sha256:fd409b7778167c3bcc836484a8f49c0e0b93d3e745d975749f83aa5d18a5822f", + "sha256:fe5d65a3ee38122003245a82303d11ac05ff36531a8f5ce4bc7d4bbc012797e1" ], - "version": "==1.12.3" - }, - "configparser": { - "hashes": [ - "sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c", - "sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df" - ], - "version": "==4.0.2" + "version": "==1.13.0" }, "core": { "editable": true, @@ -88,24 +78,29 @@ }, "cryptography": { "hashes": [ - "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c", - "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643", - "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216", - "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799", - "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a", - "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9", - "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc", - "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8", - "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53", - "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1", - "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609", - "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292", - "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e", - "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6", - "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed", - "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d" + "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.7" + "version": "==2.8" }, "fabric": { "hashes": [ @@ -114,12 +109,6 @@ ], "version": "==2.5.0" }, - "future": { - "hashes": [ - "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8" - ], - "version": "==0.17.1" - }, "grpcio": { "hashes": [ "sha256:0302331e014fc4bac028b6ad480b33f7abfe20b9bdcca7be417124dda8f22115", @@ -282,10 +271,10 @@ }, "attrs": { "hashes": [ - "sha256:ec20e7a4825331c1b5ebf261d111e16fa9612c1f7a5e1f884f12bd53a664dfd2", - "sha256:f913492e1663d3c36f502e5e9ba6cd13cf19d7fab50aa13239e420fef95e1396" + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" ], - "version": "==19.2.0" + "version": "==19.3.0" }, "black": { "hashes": [ @@ -531,11 +520,11 @@ }, "pytest": { "hashes": [ - "sha256:13c1c9b22127a77fc684eee24791efafcef343335d855e3573791c68588fe1a5", - "sha256:d8ba7be9466f55ef96ba203fc0f90d0cf212f2f927e69186e1353e30bc7f62e5" + "sha256:7e4800063ccfc306a53c461442526c5571e1462f61583506ce97e4da6a1d88c8", + "sha256:ca563435f4941d0cb34767301c27bc65c510cb82e90b9ecf9cb52dc2c63caaa0" ], "index": "pypi", - "version": "==5.2.0" + "version": "==5.2.1" }, "pyyaml": { "hashes": [ @@ -571,10 +560,10 @@ }, "virtualenv": { "hashes": [ - "sha256:680af46846662bb38c5504b78bad9ed9e4f3ba2d54f54ba42494fdf94337fe30", - "sha256:f78d81b62d3147396ac33fc9d77579ddc42cc2a98dd9ea38886f616b33bc7fb2" + "sha256:3e3597e89c73df9313f5566e8fc582bd7037938d15b05329c232ec57a11a7ad5", + "sha256:5d370508bf32e522d79096e8cbea3499d47e624ac7e11e9089f9397a0b3318df" ], - "version": "==16.7.5" + "version": "==16.7.6" }, "wcwidth": { "hashes": [ diff --git a/daemon/core/api/grpc/server.py b/daemon/core/api/grpc/server.py index 3c70ed09..11bfcd6b 100644 --- a/daemon/core/api/grpc/server.py +++ b/daemon/core/api/grpc/server.py @@ -4,7 +4,6 @@ import os import re import tempfile import time -from builtins import int from concurrent import futures from queue import Empty, Queue @@ -248,9 +247,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): """ session = self.coreemu.sessions.get(session_id) if not session: - context.abort( - grpc.StatusCode.NOT_FOUND, "session {} not found".format(session_id) - ) + context.abort(grpc.StatusCode.NOT_FOUND, f"session {session_id} not found") return session def get_node(self, session, node_id, context): @@ -266,9 +263,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): try: return session.get_node(node_id) except CoreError: - context.abort( - grpc.StatusCode.NOT_FOUND, "node {} not found".format(node_id) - ) + context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found") def CreateSession(self, request, context): """ @@ -1578,17 +1573,13 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): nem_one = request.nem_one emane_one, netif = session.emane.nemlookup(nem_one) if not emane_one or not netif: - context.abort( - grpc.StatusCode.NOT_FOUND, "nem one {} not found".format(nem_one) - ) + context.abort(grpc.StatusCode.NOT_FOUND, f"nem one {nem_one} not found") node_one = netif.node nem_two = request.nem_two emane_two, netif = session.emane.nemlookup(nem_two) if not emane_two or not netif: - context.abort( - grpc.StatusCode.NOT_FOUND, "nem two {} not found".format(nem_two) - ) + context.abort(grpc.StatusCode.NOT_FOUND, f"nem two {nem_two} not found") node_two = netif.node if emane_one.id == emane_two.id: diff --git a/daemon/core/api/tlv/coreapi.py b/daemon/core/api/tlv/coreapi.py index 1e1de8be..0fd16bf5 100644 --- a/daemon/core/api/tlv/coreapi.py +++ b/daemon/core/api/tlv/coreapi.py @@ -9,8 +9,6 @@ import socket import struct from enum import Enum -from past.builtins import basestring - from core.api.tlv import structutils from core.emulator.enumerations import ( ConfigTlvs, @@ -181,8 +179,8 @@ class CoreTlvDataString(CoreTlvData): :return: length of data packed and the packed data :rtype: tuple """ - if not isinstance(value, basestring): - raise ValueError("value not a string: %s" % type(value)) + if not isinstance(value, str): + raise ValueError(f"value not a string: {type(value)}") value = value.encode("utf-8") if len(value) < 256: @@ -222,7 +220,7 @@ class CoreTlvDataUint16List(CoreTlvData): :rtype: tuple """ if not isinstance(values, tuple): - raise ValueError("value not a tuple: %s" % values) + raise ValueError(f"value not a tuple: {values}") data = b"" for value in values: @@ -239,7 +237,8 @@ class CoreTlvDataUint16List(CoreTlvData): :param data: data to unpack :return: unpacked data """ - data_format = "!%dH" % (len(data) / 2) + size = int(len(data) / 2) + data_format = f"!{size}H" return struct.unpack(data_format, data) @classmethod @@ -437,7 +436,7 @@ class CoreTlv(object): try: return self.tlv_type_map(self.tlv_type).name except ValueError: - return "unknown tlv type: %s" % str(self.tlv_type) + return f"unknown tlv type: {self.tlv_type}" def __str__(self): """ @@ -446,11 +445,7 @@ class CoreTlv(object): :return: string representation :rtype: str """ - return "%s " % ( - self.__class__.__name__, - self.type_str(), - self.value, - ) + return f"{self.__class__.__name__} " class CoreNodeTlv(CoreTlv): @@ -736,7 +731,7 @@ class CoreMessage(object): :return: nothing """ if key in self.tlv_data: - raise KeyError("key already exists: %s (val=%s)" % (key, value)) + raise KeyError(f"key already exists: {key} (val={value})") self.tlv_data[key] = value @@ -795,7 +790,7 @@ class CoreMessage(object): try: return MessageTypes(self.message_type).name except ValueError: - return "unknown message type: %s" % str(self.message_type) + return f"unknown message type: {self.message_type}" def flag_str(self): """ @@ -812,12 +807,13 @@ class CoreMessage(object): try: message_flags.append(self.flag_map(flag).name) except ValueError: - message_flags.append("0x%x" % flag) + message_flags.append(f"0x{flag:x}") flag <<= 1 if not (self.flags & ~(flag - 1)): break - return "0x%x <%s>" % (self.flags, " | ".join(message_flags)) + message_flags = " | ".join(message_flags) + return f"0x{self.flags:x} <{message_flags}>" def __str__(self): """ @@ -826,20 +822,16 @@ class CoreMessage(object): :return: string representation :rtype: str """ - result = "%s " % ( - self.__class__.__name__, - self.type_str(), - self.flag_str(), - ) + result = f"{self.__class__.__name__} " for key in self.tlv_data: value = self.tlv_data[key] try: tlv_type = self.tlv_class.tlv_type_map(key).name except ValueError: - tlv_type = "tlv type %s" % key + tlv_type = f"tlv type {key}" - result += "\n %s: %s" % (tlv_type, value) + result += f"\n {tlv_type}: {value}" return result diff --git a/daemon/core/api/tlv/corehandlers.py b/daemon/core/api/tlv/corehandlers.py index 9a5e487a..85b7b831 100644 --- a/daemon/core/api/tlv/corehandlers.py +++ b/daemon/core/api/tlv/corehandlers.py @@ -10,7 +10,6 @@ import socketserver import sys import threading import time -from builtins import range from itertools import repeat from queue import Empty, Queue @@ -76,7 +75,7 @@ class CoreHandler(socketserver.BaseRequestHandler): self.handler_threads = [] num_threads = int(server.config["numthreads"]) if num_threads < 1: - raise ValueError("invalid number of threads: %s" % num_threads) + raise ValueError(f"invalid number of threads: {num_threads}") logging.debug("launching core server handler threads: %s", num_threads) for _ in range(num_threads): @@ -461,7 +460,7 @@ class CoreHandler(socketserver.BaseRequestHandler): try: header = self.request.recv(coreapi.CoreMessage.header_len) except IOError as e: - raise IOError("error receiving header (%s)" % e) + raise IOError(f"error receiving header ({e})") if len(header) != coreapi.CoreMessage.header_len: if len(header) == 0: @@ -479,10 +478,7 @@ class CoreHandler(socketserver.BaseRequestHandler): while len(data) < message_len: data += self.request.recv(message_len - len(data)) if len(data) > message_len: - error_message = ( - "received message length does not match received data (%s != %s)" - % (len(data), message_len) - ) + error_message = f"received message length does not match received data ({len(data)} != {message_len})" logging.error(error_message) raise IOError(error_message) @@ -574,11 +570,7 @@ class CoreHandler(socketserver.BaseRequestHandler): ) except KeyError: # multiple TLVs of same type cause KeyError exception - reply_message = "CoreMessage (type %d flags %d length %d)" % ( - message_type, - message_flags, - message_length, - ) + reply_message = f"CoreMessage (type {message_type} flags {message_flags} length {message_length})" logging.debug("sending reply:\n%s", reply_message) @@ -1000,7 +992,7 @@ class CoreHandler(socketserver.BaseRequestHandler): RegisterTlvs.EXECUTE_SERVER.value, execute_server ) tlv_data += coreapi.CoreRegisterTlv.pack( - RegisterTlvs.SESSION.value, "%s" % sid + RegisterTlvs.SESSION.value, str(sid) ) message = coreapi.CoreRegMessage.pack(0, tlv_data) replies.append(message) @@ -1105,7 +1097,7 @@ class CoreHandler(socketserver.BaseRequestHandler): self.session.mobility.config_reset(node_id) self.session.emane.config_reset(node_id) else: - raise Exception("cant handle config all: %s" % message_type) + raise Exception(f"cant handle config all: {message_type}") return replies @@ -1159,7 +1151,7 @@ class CoreHandler(socketserver.BaseRequestHandler): if metadata_configs is None: metadata_configs = {} data_values = "|".join( - ["%s=%s" % (x, metadata_configs[x]) for x in metadata_configs] + [f"{x}={metadata_configs[x]}" for x in metadata_configs] ) data_types = tuple(ConfigDataTypes.STRING.value for _ in metadata_configs) config_response = ConfigData( @@ -1240,7 +1232,7 @@ class CoreHandler(socketserver.BaseRequestHandler): services = sorted(group_map[group], key=lambda x: x.name.lower()) logging.debug("sorted services for group(%s): %s", group, services) end_index = start_index + len(services) - 1 - group_strings.append("%s:%s-%s" % (group, start_index, end_index)) + group_strings.append(f"{group}:{start_index}-{end_index}") start_index += len(services) for service_name in services: captions.append(service_name.name) @@ -1715,24 +1707,24 @@ class CoreHandler(socketserver.BaseRequestHandler): ): status = self.session.services.stop_service(node, service) if status: - fail += "Stop %s," % service.name + fail += f"Stop {service.name}," if ( event_type == EventTypes.START.value or event_type == EventTypes.RESTART.value ): status = self.session.services.startup_service(node, service) if status: - fail += "Start %s(%s)," % service.name + fail += f"Start ({service.name})," if event_type == EventTypes.PAUSE.value: status = self.session.services.validate_service(node, service) if status: - fail += "%s," % service.name + fail += f"{service.name}," if event_type == EventTypes.RECONFIGURE.value: self.session.services.service_reconfigure(node, service) fail_data = "" if len(fail) > 0: - fail_data += "Fail:" + fail + fail_data += f"Fail:{fail}" unknown_data = "" num = len(unknown) if num > 0: @@ -1742,14 +1734,14 @@ class CoreHandler(socketserver.BaseRequestHandler): unknown_data += ", " num -= 1 logging.warning("Event requested for unknown service(s): %s", unknown_data) - unknown_data = "Unknown:" + unknown_data + unknown_data = f"Unknown:{unknown_data}" event_data = EventData( node=node_id, event_type=event_type, name=name, data=fail_data + ";" + unknown_data, - time="%s" % time.time(), + time=str(time.time()), ) self.session.broadcast_event(event_data) @@ -1770,7 +1762,7 @@ class CoreHandler(socketserver.BaseRequestHandler): thumb = message.get_tlv(SessionTlvs.THUMB.value) user = message.get_tlv(SessionTlvs.USER.value) logging.debug( - "SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str) + "SESSION message flags=0x%x sessions=%s", message.flags, session_id_str ) if message.flags == 0: @@ -1941,7 +1933,7 @@ class CoreHandler(socketserver.BaseRequestHandler): # service customizations service_configs = self.session.services.all_configs() for node_id, service in service_configs: - opaque = "service:%s" % service.name + opaque = f"service:{service.name}" data_types = tuple( repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys)) ) @@ -1977,7 +1969,7 @@ class CoreHandler(socketserver.BaseRequestHandler): file_data = FileData( message_type=MessageFlags.ADD.value, name=str(file_name), - type="hook:%s" % state, + type=f"hook:{state}", data=str(config_data), ) self.session.broadcast_file(file_data) @@ -1993,7 +1985,7 @@ class CoreHandler(socketserver.BaseRequestHandler): metadata_configs = self.session.metadata.get_configs() if metadata_configs: data_values = "|".join( - ["%s=%s" % (x, metadata_configs[x]) for x in metadata_configs] + [f"{x}={metadata_configs[x]}" for x in metadata_configs] ) data_types = tuple( ConfigDataTypes.STRING.value @@ -2042,7 +2034,7 @@ class CoreUdpHandler(CoreHandler): data = self.request[0] header = data[: coreapi.CoreMessage.header_len] if len(header) < coreapi.CoreMessage.header_len: - raise IOError("error receiving header (received %d bytes)" % len(header)) + raise IOError(f"error receiving header (received {len(header)} bytes)") message_type, message_flags, message_len = coreapi.CoreMessage.unpack_header( header @@ -2137,7 +2129,7 @@ class CoreUdpHandler(CoreHandler): :return: """ raise Exception( - "Unable to queue %s message for later processing using UDP!" % msg + f"Unable to queue {msg} message for later processing using UDP!" ) def sendall(self, data): diff --git a/daemon/core/api/tlv/structutils.py b/daemon/core/api/tlv/structutils.py index 28e22a27..41358848 100644 --- a/daemon/core/api/tlv/structutils.py +++ b/daemon/core/api/tlv/structutils.py @@ -4,8 +4,6 @@ Utilities for working with python struct data. import logging -from past.builtins import basestring - def pack_values(clazz, packers): """ @@ -31,7 +29,7 @@ def pack_values(clazz, packers): # only pack actual values and avoid packing empty strings # protobuf defaults to empty strings and does no imply a value to set - if value is None or (isinstance(value, basestring) and not value): + if value is None or (isinstance(value, str) and not value): continue # transform values as needed diff --git a/daemon/core/config.py b/daemon/core/config.py index f63ad59a..e55d5f17 100644 --- a/daemon/core/config.py +++ b/daemon/core/config.py @@ -40,10 +40,8 @@ class ConfigShim(object): """ group_strings = [] for config_group in config_groups: - group_string = "%s:%s-%s" % ( - config_group.name, - config_group.start, - config_group.stop, + group_string = ( + f"{config_group.name}:{config_group.start}-{config_group.stop}" ) group_strings.append(group_string) return "|".join(group_strings) @@ -74,7 +72,7 @@ class ConfigShim(object): if not captions: captions = configuration.label else: - captions += "|%s" % configuration.label + captions += f"|{configuration.label}" data_types.append(configuration.type.value) @@ -83,11 +81,11 @@ class ConfigShim(object): _id = configuration.id config_value = config.get(_id, configuration.default) - key_value = "%s=%s" % (_id, config_value) + key_value = f"{_id}={config_value}" if not key_values: key_values = key_value else: - key_values += "|%s" % key_value + key_values += f"|{key_value}" groups_str = cls.groups_to_str(configurable_options.config_groups()) return ConfigData( @@ -130,13 +128,7 @@ class Configuration(object): self.label = label def __str__(self): - return "%s(id=%s, type=%s, default=%s, options=%s)" % ( - self.__class__.__name__, - self.id, - self.type, - self.default, - self.options, - ) + return f"{self.__class__.__name__}(id={self.id}, type={self.type}, default={self.default}, options={self.options})" class ConfigurableManager(object): @@ -333,7 +325,7 @@ class ModelManager(ConfigurableManager): # get model class to configure model_class = self.models.get(model_name) if not model_class: - raise ValueError("%s is an invalid model" % model_name) + raise ValueError(f"{model_name} is an invalid model") # retrieve default values model_config = self.get_model_config(node_id, model_name) @@ -361,7 +353,7 @@ class ModelManager(ConfigurableManager): # get model class to configure model_class = self.models.get(model_name) if not model_class: - raise ValueError("%s is an invalid model" % model_name) + raise ValueError(f"{model_name} is an invalid model") config = self.get_configs(node_id=node_id, config_type=model_name) if not config: diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 1f829b18..33edc342 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -4,10 +4,8 @@ commeffect.py: EMANE CommEffect model for CORE import logging import os -from builtins import int from lxml import etree -from past.builtins import basestring from core.config import ConfigGroup from core.emane import emanemanifest, emanemodel @@ -26,7 +24,7 @@ def convert_none(x): """ Helper to use 0 for None values. """ - if isinstance(x, basestring): + if isinstance(x, str): x = float(x) if x is None: return 0 @@ -75,9 +73,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): shim_name = emanexml.shim_file_name(self, interface) # create and write nem document - nem_element = etree.Element( - "nem", name="%s NEM" % self.name, type="unstructured" - ) + nem_element = etree.Element("nem", name=f"{self.name} NEM", type="unstructured") transport_type = "virtual" if interface and interface.transport_type == "raw": transport_type = "raw" @@ -92,7 +88,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): # create and write shim document shim_element = etree.Element( - "shim", name="%s SHIM" % self.name, library=self.shim_library + "shim", name=f"{self.name} SHIM", library=self.shim_library ) # append all shim options (except filterfile) to shimdoc diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 91553b5a..743f90b2 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -227,7 +227,7 @@ class EmaneManager(ModelManager): with self._emane_node_lock: if emane_net.id in self._emane_nets: raise KeyError( - "non-unique EMANE object id %s for %s" % (emane_net.id, emane_net) + f"non-unique EMANE object id {emane_net.id} for {emane_net}" ) self._emane_nets[emane_net.id] = emane_net @@ -342,7 +342,7 @@ class EmaneManager(ModelManager): try: with open(emane_nems_filename, "w") as f: for nodename, ifname, nemid in nems: - f.write("%s %s %s\n" % (nodename, ifname, nemid)) + f.write(f"{nodename} {ifname} {nemid}\n") except IOError: logging.exception("Error writing EMANE NEMs file: %s") @@ -535,7 +535,7 @@ class EmaneManager(ModelManager): logging.info("setting user-defined EMANE log level: %d", cfgloglevel) loglevel = str(cfgloglevel) - emanecmd = "emane -d -l %s" % loglevel + emanecmd = f"emane -d -l {loglevel}" if realtime: emanecmd += " -r" @@ -580,11 +580,9 @@ class EmaneManager(ModelManager): node.node_net_client.create_route(eventgroup, eventdev) # start emane - args = "%s -f %s %s" % ( - emanecmd, - os.path.join(path, "emane%d.log" % n), - os.path.join(path, "platform%d.xml" % n), - ) + log_file = os.path.join(path, f"emane{n}.log") + platform_xml = os.path.join(path, f"platform{n}.xml") + args = f"{emanecmd} -f {log_file} {platform_xml}" output = node.node_net_cmd(args) logging.info("node(%s) emane daemon running: %s", node.name, args) logging.info("node(%s) emane daemon output: %s", node.name, output) @@ -593,8 +591,9 @@ class EmaneManager(ModelManager): return path = self.session.session_dir - emanecmd += " -f %s" % os.path.join(path, "emane.log") - emanecmd += " %s" % os.path.join(path, "platform.xml") + log_file = os.path.join(path, "emane.log") + platform_xml = os.path.join(path, "platform.xml") + emanecmd += f" -f {log_file} {platform_xml}" utils.check_cmd(emanecmd, cwd=path) self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path)) logging.info("host emane daemon running: %s", emanecmd) @@ -797,7 +796,7 @@ class EmaneManager(ModelManager): node = self.session.get_node(n) except CoreError: logging.exception( - "location event NEM %s has no corresponding node %s" % (nemid, n) + "location event NEM %s has no corresponding node %s", nemid, n ) return False diff --git a/daemon/core/emane/emanemanifest.py b/daemon/core/emane/emanemanifest.py index 13cff8f2..a6583b9e 100644 --- a/daemon/core/emane/emanemanifest.py +++ b/daemon/core/emane/emanemanifest.py @@ -115,7 +115,7 @@ def parse(manifest_path, defaults): # define description and account for gui quirks config_descriptions = config_name if config_name.endswith("uri"): - config_descriptions = "%s file" % config_descriptions + config_descriptions = f"{config_descriptions} file" configuration = Configuration( _id=config_name, diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index 5451506f..e0ceee2f 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -210,7 +210,7 @@ class EmaneNet(CoreNetworkBase): nemid = self.getnemid(netif) ifname = netif.localname if nemid is None: - logging.info("nemid for %s is unknown" % ifname) + logging.info("nemid for %s is unknown", ifname) continue x, y, z = netif.node.getposition() lat, lon, alt = self.session.location.getgeo(x, y, z) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 249e81b6..91e662ea 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -62,5 +62,5 @@ class EmaneTdmaModel(emanemodel.EmaneModel): logging.info( "setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device ) - args = "emaneevent-tdmaschedule -i %s %s" % (event_device, schedule) + args = f"emaneevent-tdmaschedule -i {event_device} {schedule}" utils.check_cmd(args) diff --git a/daemon/core/emulator/distributed.py b/daemon/core/emulator/distributed.py index 83576434..03e043eb 100644 --- a/daemon/core/emulator/distributed.py +++ b/daemon/core/emulator/distributed.py @@ -128,7 +128,7 @@ class DistributedController(object): """ server = DistributedServer(name, host) self.servers[name] = server - cmd = "mkdir -p %s" % self.session.session_dir + cmd = f"mkdir -p {self.session.session_dir}" server.remote_cmd(cmd) def execute(self, func): @@ -158,7 +158,7 @@ class DistributedController(object): # remove all remote session directories for name in self.servers: server = self.servers[name] - cmd = "rm -rf %s" % self.session.session_dir + cmd = f"rm -rf {self.session.session_dir}" server.remote_cmd(cmd) # clear tunnels diff --git a/daemon/core/emulator/emudata.py b/daemon/core/emulator/emudata.py index d11d1e0e..5a38c69c 100644 --- a/daemon/core/emulator/emudata.py +++ b/daemon/core/emulator/emudata.py @@ -284,7 +284,7 @@ class InterfaceData(object): :return: ip4 string or None """ if self.has_ip4(): - return "%s/%s" % (self.ip4, self.ip4_mask) + return f"{self.ip4}/{self.ip4_mask}" else: return None @@ -295,7 +295,7 @@ class InterfaceData(object): :return: ip4 string or None """ if self.has_ip6(): - return "%s/%s" % (self.ip6, self.ip6_mask) + return f"{self.ip6}/{self.ip6_mask}" else: return None diff --git a/daemon/core/emulator/session.py b/daemon/core/emulator/session.py index d962da28..d80e5e25 100644 --- a/daemon/core/emulator/session.py +++ b/daemon/core/emulator/session.py @@ -90,7 +90,7 @@ class Session(object): self.master = False # define and create session directory when desired - self.session_dir = os.path.join(tempfile.gettempdir(), "pycore.%s" % self.id) + self.session_dir = os.path.join(tempfile.gettempdir(), f"pycore.{self.id}") if mkdir: os.mkdir(self.session_dir) @@ -164,7 +164,7 @@ class Session(object): """ node_class = NODES.get(_type) if node_class is None: - raise CoreError("invalid node type: %s" % _type) + raise CoreError(f"invalid node type: {_type}") return node_class @classmethod @@ -178,7 +178,7 @@ class Session(object): """ node_type = NODES_TYPE.get(_class) if node_type is None: - raise CoreError("invalid node class: %s" % _class) + raise CoreError(f"invalid node class: {_class}") return node_type def _link_nodes(self, node_one_id, node_two_id): @@ -254,7 +254,7 @@ class Session(object): """ objects = [x for x in objects if x] if len(objects) < 2: - raise CoreError("wireless link failure: %s" % objects) + raise CoreError(f"wireless link failure: {objects}") logging.debug( "handling wireless linking objects(%s) connect(%s)", objects, connect ) @@ -665,13 +665,13 @@ class Session(object): node_options = NodeOptions() name = node_options.name if not name: - name = "%s%s" % (node_class.__name__, _id) + name = f"{node_class.__name__}{_id}" # verify distributed server server = self.distributed.servers.get(node_options.emulation_server) if node_options.emulation_server is not None and server is None: raise CoreError( - "invalid distributed server: %s" % node_options.emulation_server + f"invalid distributed server: {node_options.emulation_server}" ) # create node @@ -854,7 +854,7 @@ class Session(object): :return: nothing """ # hack to conform with old logic until updated - state = ":%s" % state + state = f":{state}" self.set_hook(state, file_name, source_name, data) def add_node_file(self, node_id, source_name, file_name, data): @@ -1066,7 +1066,7 @@ class Session(object): self.run_state_hooks(state_value) if send_event: - event_data = EventData(event_type=state_value, time="%s" % time.time()) + event_data = EventData(event_type=state_value, time=str(time.time())) self.broadcast_event(event_data) def write_state(self, state): @@ -1078,7 +1078,7 @@ class Session(object): """ try: state_file = open(self._state_file, "w") - state_file.write("%d %s\n" % (state, EventTypes(self.state).name)) + state_file.write(f"{state} {EventTypes(self.state).name}\n") state_file.close() except IOError: logging.exception("error writing state file: %s", state) @@ -1195,9 +1195,9 @@ class Session(object): try: hook(state) except Exception: - message = "exception occured when running %s state hook: %s" % ( - EventTypes(self.state).name, - hook, + state_name = EventTypes(self.state).name + message = ( + f"exception occured when running {state_name} state hook: {hook}" ) logging.exception(message) self.exception( @@ -1258,16 +1258,16 @@ class Session(object): :rtype: dict """ env = os.environ.copy() - env["SESSION"] = "%s" % self.id - env["SESSION_SHORT"] = "%s" % self.short_session_id() - env["SESSION_DIR"] = "%s" % self.session_dir - env["SESSION_NAME"] = "%s" % self.name - env["SESSION_FILENAME"] = "%s" % self.file_name - env["SESSION_USER"] = "%s" % self.user - env["SESSION_NODE_COUNT"] = "%s" % self.get_node_count() + env["SESSION"] = str(self.id) + env["SESSION_SHORT"] = self.short_session_id() + env["SESSION_DIR"] = self.session_dir + env["SESSION_NAME"] = str(self.name) + env["SESSION_FILENAME"] = str(self.file_name) + env["SESSION_USER"] = str(self.user) + env["SESSION_NODE_COUNT"] = str(self.get_node_count()) if state: - env["SESSION_STATE"] = "%s" % self.state + env["SESSION_STATE"] = str(self.state) # attempt to read and add environment config file environment_config_file = os.path.join(constants.CORE_CONF_DIR, "environment") @@ -1356,7 +1356,7 @@ class Session(object): with self._nodes_lock: if node.id in self.nodes: node.shutdown() - raise CoreError("duplicate node id %s for %s" % (node.id, node.name)) + raise CoreError(f"duplicate node id {node.id} for {node.name}") self.nodes[node.id] = node return node @@ -1371,7 +1371,7 @@ class Session(object): :raises core.CoreError: when node does not exist """ if _id not in self.nodes: - raise CoreError("unknown node id %s" % _id) + raise CoreError(f"unknown node id {_id}") return self.nodes[_id] def delete_node(self, _id): @@ -1416,9 +1416,7 @@ class Session(object): with open(file_path, "w") as f: for _id in self.nodes.keys(): node = self.nodes[_id] - f.write( - "%s %s %s %s\n" % (_id, node.name, node.apitype, type(node)) - ) + f.write(f"{_id} {node.name} {node.apitype} {type(node)}\n") except IOError: logging.exception("error writing nodes file") @@ -1585,7 +1583,7 @@ class Session(object): interface names, where length may be limited. """ ssid = (self.id >> 8) ^ (self.id & ((1 << 8) - 1)) - return "%x" % ssid + return f"{ssid:x}" def boot_nodes(self): """ @@ -1670,7 +1668,7 @@ class Session(object): def get_control_net(self, net_index): # TODO: all nodes use an integer id and now this wants to use a string - _id = "ctrl%dnet" % net_index + _id = f"ctrl{net_index}net" return self.get_node(_id) def add_remove_control_net(self, net_index, remove=False, conf_required=True): @@ -1718,7 +1716,7 @@ class Session(object): return None # build a new controlnet bridge - _id = "ctrl%dnet" % net_index + _id = f"ctrl{net_index}net" # use the updown script for control net 0 only. updown_script = None @@ -1797,13 +1795,12 @@ class Session(object): control_ip = node.id try: - addrlist = [ - "%s/%s" - % (control_net.prefix.addr(control_ip), control_net.prefix.prefixlen) - ] + address = control_net.prefix.addr(control_ip) + prefix = control_net.prefix.prefixlen + addrlist = [f"{address}/{prefix}"] except ValueError: - msg = "Control interface not added to node %s. " % node.id - msg += "Invalid control network prefix (%s). " % control_net.prefix + msg = f"Control interface not added to node {node.id}. " + msg += f"Invalid control network prefix ({control_net.prefix}). " msg += "A longer prefix length may be required for this many nodes." logging.exception(msg) return @@ -1811,7 +1808,7 @@ class Session(object): interface1 = node.newnetif( net=control_net, ifindex=control_net.CTRLIF_IDX_BASE + net_index, - ifname="ctrl%d" % net_index, + ifname=f"ctrl{net_index}", hwaddr=MacAddress.random(), addrlist=addrlist, ) @@ -1834,7 +1831,7 @@ class Session(object): logging.exception("error retrieving control net node") return - header = "CORE session %s host entries" % self.id + header = f"CORE session {self.id} host entries" if remove: logging.info("Removing /etc/hosts file entries.") utils.file_demunge("/etc/hosts", header) @@ -1844,9 +1841,10 @@ class Session(object): for interface in control_net.netifs(): name = interface.node.name for address in interface.addrlist: - entries.append("%s %s" % (address.split("/")[0], name)) + address = address.split("/")[0] + entries.append(f"{address} {name}") - logging.info("Adding %d /etc/hosts file entries." % len(entries)) + logging.info("Adding %d /etc/hosts file entries.", len(entries)) utils.file_munge("/etc/hosts", header, "\n".join(entries) + "\n") diff --git a/daemon/core/errors.py b/daemon/core/errors.py index 5b76abb3..f5c38b5b 100644 --- a/daemon/core/errors.py +++ b/daemon/core/errors.py @@ -10,11 +10,9 @@ class CoreCommandError(subprocess.CalledProcessError): """ def __str__(self): - return "Command(%s), Status(%s):\nstdout: %s\nstderr: %s" % ( - self.cmd, - self.returncode, - self.output, - self.stderr, + return ( + f"Command({self.cmd}), Status({self.returncode}):\n" + f"stdout: {self.output}\nstderr: {self.stderr}" ) diff --git a/daemon/core/location/corelocation.py b/daemon/core/location/corelocation.py index b3e62153..5f9e11e3 100644 --- a/daemon/core/location/corelocation.py +++ b/daemon/core/location/corelocation.py @@ -128,8 +128,6 @@ class CoreLocation(object): z, ) lat, lon = self.refgeo[:2] - # self.info("getgeo(%s,%s,%s) e=%s n=%s zone=%s lat,lon,alt=" \ - # "%.3f,%.3f,%.3f" % (x, y, z, e, n, zone, lat, lon, alt)) return lat, lon, alt def getxyz(self, lat, lon, alt): diff --git a/daemon/core/location/event.py b/daemon/core/location/event.py index b3170083..1872ac18 100644 --- a/daemon/core/location/event.py +++ b/daemon/core/location/event.py @@ -5,8 +5,7 @@ event.py: event loop implementation using a heap queue and threads. import heapq import threading import time - -from past.builtins import cmp +from functools import total_ordering class Timer(threading.Thread): @@ -70,6 +69,7 @@ class Timer(threading.Thread): self.finished.set() +@total_ordering class Event(object): """ Provides event objects that can be used within the EventLoop class. @@ -92,18 +92,11 @@ class Event(object): self.kwds = kwds self.canceled = False - def __cmp__(self, other): - """ - Comparison function. - - :param Event other: event to compare with - :return: comparison result - :rtype: int - """ - tmp = cmp(self.time, other.time) - if tmp == 0: - tmp = cmp(self.eventnum, other.eventnum) - return tmp + def __lt__(self, other): + result = self.time < other.time + if result: + result = self.eventnum < other.eventnum + return result def run(self): """ diff --git a/daemon/core/location/mobility.py b/daemon/core/location/mobility.py index eae46ce4..f2b49818 100644 --- a/daemon/core/location/mobility.py +++ b/daemon/core/location/mobility.py @@ -8,7 +8,6 @@ import math import os import threading import time -from builtins import int from functools import total_ordering from core import utils @@ -166,15 +165,16 @@ class MobilityManager(ModelManager): elif model.state == model.STATE_PAUSED: event_type = EventTypes.PAUSE.value - data = "start=%d" % int(model.lasttime - model.timezero) - data += " end=%d" % int(model.endtime) + start_time = int(model.lasttime - model.timezero) + end_time = int(model.endtime) + data = f"start={start_time} end={end_time}" event_data = EventData( node=model.id, event_type=event_type, - name="mobility:%s" % model.name, + name=f"mobility:{model.name}", data=data, - time="%s" % time.time(), + time=str(time.time()), ) self.session.broadcast_event(event_data) @@ -992,7 +992,7 @@ class Ns2ScriptedMobility(WayPointMobility): "ns-2 scripted mobility failed to load file: %s", self.file ) return - logging.info("reading ns-2 script file: %s" % filename) + logging.info("reading ns-2 script file: %s", filename) ln = 0 ix = iy = iz = None inodenum = None @@ -1113,7 +1113,7 @@ class Ns2ScriptedMobility(WayPointMobility): :return: nothing """ if self.autostart == "": - logging.info("not auto-starting ns-2 script for %s" % self.wlan.name) + logging.info("not auto-starting ns-2 script for %s", self.wlan.name) return try: t = float(self.autostart) @@ -1125,9 +1125,7 @@ class Ns2ScriptedMobility(WayPointMobility): ) return self.movenodesinitial() - logging.info( - "scheduling ns-2 script for %s autostart at %s" % (self.wlan.name, t) - ) + logging.info("scheduling ns-2 script for %s autostart at %s", self.wlan.name, t) self.state = self.STATE_RUNNING self.session.event_loop.add_event(t, self.run) @@ -1188,7 +1186,7 @@ class Ns2ScriptedMobility(WayPointMobility): if filename is None or filename == "": return filename = self.findfile(filename) - args = "/bin/sh %s %s" % (filename, typestr) + args = f"/bin/sh {filename} {typestr}" utils.check_cmd( args, cwd=self.session.session_dir, env=self.session.get_environment() ) diff --git a/daemon/core/nodes/base.py b/daemon/core/nodes/base.py index 4e9de039..fcd75505 100644 --- a/daemon/core/nodes/base.py +++ b/daemon/core/nodes/base.py @@ -46,7 +46,7 @@ class NodeBase(object): _id = session.get_node_id() self.id = _id if name is None: - name = "o%s" % self.id + name = f"o{self.id}" self.name = name self.server = server @@ -265,7 +265,7 @@ class CoreNodeBase(NodeBase): """ if self.nodedir is None: self.nodedir = os.path.join(self.session.session_dir, self.name + ".conf") - self.net_cmd("mkdir -p %s" % self.nodedir) + self.net_cmd(f"mkdir -p {self.nodedir}") self.tmpnodedir = True else: self.tmpnodedir = False @@ -281,7 +281,7 @@ class CoreNodeBase(NodeBase): return if self.tmpnodedir: - self.net_cmd("rm -rf %s" % self.nodedir) + self.net_cmd(f"rm -rf {self.nodedir}") def addnetif(self, netif, ifindex): """ @@ -292,7 +292,7 @@ class CoreNodeBase(NodeBase): :return: nothing """ if ifindex in self._netif: - raise ValueError("ifindex %s already exists" % ifindex) + raise ValueError(f"ifindex {ifindex} already exists") self._netif[ifindex] = netif # TODO: this should have probably been set ahead, seems bad to me, check for failure and fix netif.netindex = ifindex @@ -305,7 +305,7 @@ class CoreNodeBase(NodeBase): :return: nothing """ if ifindex not in self._netif: - raise ValueError("ifindex %s does not exist" % ifindex) + raise ValueError(f"ifindex {ifindex} does not exist") netif = self._netif.pop(ifindex) netif.shutdown() del netif @@ -334,7 +334,7 @@ class CoreNodeBase(NodeBase): :return: nothing """ if ifindex not in self._netif: - raise ValueError("ifindex %s does not exist" % ifindex) + raise ValueError(f"ifindex {ifindex} does not exist") self._netif[ifindex].attachnet(net) def detachnet(self, ifindex): @@ -345,7 +345,7 @@ class CoreNodeBase(NodeBase): :return: nothing """ if ifindex not in self._netif: - raise ValueError("ifindex %s does not exist" % ifindex) + raise ValueError(f"ifindex {ifindex} does not exist") self._netif[ifindex].detachnet() def setposition(self, x=None, y=None, z=None): @@ -472,7 +472,7 @@ class CoreNode(CoreNodeBase): :rtype: bool """ try: - self.net_cmd("kill -0 %s" % self.pid) + self.net_cmd(f"kill -0 {self.pid}") except CoreCommandError: return False @@ -492,11 +492,12 @@ class CoreNode(CoreNodeBase): raise ValueError("starting a node that is already up") # create a new namespace for this node using vnoded - vnoded = "{cmd} -v -c {name} -l {name}.log -p {name}.pid".format( - cmd=VNODED_BIN, name=self.ctrlchnlname + vnoded = ( + f"{VNODED_BIN} -v -c {self.ctrlchnlname} -l {self.ctrlchnlname}.log " + f"-p {self.ctrlchnlname}.pid" ) if self.nodedir: - vnoded += " -C %s" % self.nodedir + vnoded += f" -C {self.nodedir}" env = self.session.get_environment(state=False) env["NODE_NUMBER"] = str(self.id) env["NODE_NAME"] = str(self.name) @@ -545,13 +546,13 @@ class CoreNode(CoreNodeBase): # kill node process if present try: - self.net_cmd("kill -9 %s" % self.pid) + self.net_cmd(f"kill -9 {self.pid}") except CoreCommandError: logging.exception("error killing process") # remove node directory if present try: - self.net_cmd("rm -rf %s" % self.ctrlchnlname) + self.net_cmd(f"rm -rf {self.ctrlchnlname}") except CoreCommandError: logging.exception("error removing node directory") @@ -592,9 +593,7 @@ class CoreNode(CoreNodeBase): if self.server is None: return terminal else: - return "ssh -X -f {host} xterm -e {terminal}".format( - host=self.server.host, terminal=terminal - ) + return f"ssh -X -f {self.server.host} xterm -e {terminal}" def privatedir(self, path): """ @@ -604,11 +603,11 @@ class CoreNode(CoreNodeBase): :return: nothing """ if path[0] != "/": - raise ValueError("path not fully qualified: %s" % path) + raise ValueError(f"path not fully qualified: {path}") hostpath = os.path.join( self.nodedir, os.path.normpath(path).strip("/").replace("/", ".") ) - self.net_cmd("mkdir -p %s" % hostpath) + self.net_cmd(f"mkdir -p {hostpath}") self.mount(hostpath, path) def mount(self, source, target): @@ -622,8 +621,8 @@ class CoreNode(CoreNodeBase): """ source = os.path.abspath(source) logging.debug("node(%s) mounting: %s at %s", self.name, source, target) - self.node_net_cmd("mkdir -p %s" % target) - self.node_net_cmd("%s -n --bind %s %s" % (MOUNT_BIN, source, target)) + self.node_net_cmd(f"mkdir -p {target}") + self.node_net_cmd(f"{MOUNT_BIN} -n --bind {source} {target}") self._mounts.append((source, target)) def newifindex(self): @@ -650,22 +649,22 @@ class CoreNode(CoreNodeBase): ifindex = self.newifindex() if ifname is None: - ifname = "eth%d" % ifindex + ifname = f"eth{ifindex}" sessionid = self.session.short_session_id() try: - suffix = "%x.%s.%s" % (self.id, ifindex, sessionid) + suffix = f"{self.id:x}.{ifindex}.{sessionid}" except TypeError: - suffix = "%s.%s.%s" % (self.id, ifindex, sessionid) + suffix = f"{self.id}.{ifindex}.{sessionid}" - localname = "veth" + suffix + localname = f"veth{suffix}" if len(localname) >= 16: - raise ValueError("interface local name (%s) too long" % localname) + raise ValueError(f"interface local name ({localname}) too long") name = localname + "p" if len(name) >= 16: - raise ValueError("interface name (%s) too long" % name) + raise ValueError(f"interface name ({name}) too long") veth = Veth( self.session, self, name, localname, start=self.up, server=self.server @@ -679,16 +678,9 @@ class CoreNode(CoreNodeBase): veth.name = ifname if self.up: - # TODO: potentially find better way to query interface ID - # retrieve interface information - output = self.node_net_client.device_show(veth.name) - logging.debug("interface command output: %s", output) - output = output.split("\n") - veth.flow_id = int(output[0].strip().split(":")[0]) + 1 - logging.debug("interface flow index: %s - %s", veth.name, veth.flow_id) - # TODO: mimic packed hwaddr - # veth.hwaddr = MacAddress.from_string(output[1].strip().split()[1]) - logging.debug("interface mac: %s - %s", veth.name, veth.hwaddr) + flow_id = self.node_net_client.get_ifindex(veth.name) + veth.flow_id = int(flow_id) + logging.info("interface flow index: %s - %s", veth.name, veth.flow_id) try: # add network interface to the node. If unsuccessful, destroy the @@ -716,10 +708,10 @@ class CoreNode(CoreNodeBase): ifindex = self.newifindex() if ifname is None: - ifname = "eth%d" % ifindex + ifname = f"eth{ifindex}" sessionid = self.session.short_session_id() - localname = "tap%s.%s.%s" % (self.id, ifindex, sessionid) + localname = f"tap{self.id}.{ifindex}.{sessionid}" name = ifname tuntap = TunTap(self.session, self, name, localname, start=self.up) @@ -778,7 +770,7 @@ class CoreNode(CoreNodeBase): try: interface.deladdr(addr) except ValueError: - logging.exception("trying to delete unknown address: %s" % addr) + logging.exception("trying to delete unknown address: %s", addr) if self.up: self.node_net_client.delete_address(interface.name, str(addr)) @@ -850,11 +842,11 @@ class CoreNode(CoreNodeBase): logging.info("adding file from %s to %s", srcname, filename) directory = os.path.dirname(filename) if self.server is None: - self.client.check_cmd("mkdir -p %s" % directory) - self.client.check_cmd("mv %s %s" % (srcname, filename)) + self.client.check_cmd(f"mkdir -p {directory}") + self.client.check_cmd(f"mv {srcname} {filename}") self.client.check_cmd("sync") else: - self.net_cmd("mkdir -p %s" % directory) + self.net_cmd(f"mkdir -p {directory}") self.server.remote_put(srcname, filename) def hostfilename(self, filename): @@ -866,7 +858,7 @@ class CoreNode(CoreNodeBase): """ dirname, basename = os.path.split(filename) if not basename: - raise ValueError("no basename for filename: %s" % filename) + raise ValueError(f"no basename for filename: {filename}") if dirname and dirname[0] == "/": dirname = dirname[1:] dirname = dirname.replace("/", ".") @@ -891,9 +883,9 @@ class CoreNode(CoreNodeBase): open_file.write(contents) os.chmod(open_file.name, mode) else: - self.net_cmd("mkdir -m %o -p %s" % (0o755, dirname)) + self.net_cmd(f"mkdir -m {0o755:o} -p {dirname}") self.server.remote_put_temp(hostfilename, contents) - self.net_cmd("chmod %o %s" % (mode, hostfilename)) + self.net_cmd(f"chmod {mode:o} {hostfilename}") logging.debug( "node(%s) added file: %s; mode: 0%o", self.name, hostfilename, mode ) @@ -914,7 +906,7 @@ class CoreNode(CoreNodeBase): else: self.server.remote_put(srcfilename, hostfilename) if mode is not None: - self.net_cmd("chmod %o %s" % (mode, hostfilename)) + self.net_cmd(f"chmod {mode:o} {hostfilename}") logging.info( "node(%s) copied file: %s; mode: %s", self.name, hostfilename, mode ) diff --git a/daemon/core/nodes/client.py b/daemon/core/nodes/client.py index 632e12bc..299b8135 100644 --- a/daemon/core/nodes/client.py +++ b/daemon/core/nodes/client.py @@ -51,7 +51,7 @@ class VnodeClient(object): pass def create_cmd(self, args): - return "%s -c %s -- %s" % (VCMD_BIN, self.ctrlchnlname, args) + return f"{VCMD_BIN} -c {self.ctrlchnlname} -- {args}" def check_cmd(self, args, wait=True): """ diff --git a/daemon/core/nodes/docker.py b/daemon/core/nodes/docker.py index 17d7578a..369f462b 100644 --- a/daemon/core/nodes/docker.py +++ b/daemon/core/nodes/docker.py @@ -19,23 +19,18 @@ class DockerClient(object): def create_container(self): self.run( - "docker run -td --init --net=none --hostname {name} --name {name} " - "--sysctl net.ipv6.conf.all.disable_ipv6=0 " - "{image} /bin/bash".format( - name=self.name, - image=self.image - )) + f"docker run -td --init --net=none --hostname {self.name} --name {self.name} " + f"--sysctl net.ipv6.conf.all.disable_ipv6=0 {self.image} /bin/bash" + ) self.pid = self.get_pid() return self.pid def get_info(self): - args = "docker inspect {name}".format(name=self.name) + args = f"docker inspect {self.name}" output = self.run(args) data = json.loads(output) if not data: - raise CoreCommandError( - -1, args, "docker({name}) not present".format(name=self.name) - ) + raise CoreCommandError(-1, args, f"docker({self.name}) not present") return data[0] def is_alive(self): @@ -46,43 +41,28 @@ class DockerClient(object): return False def stop_container(self): - self.run("docker rm -f {name}".format( - name=self.name - )) + self.run(f"docker rm -f {self.name}") def check_cmd(self, cmd): logging.info("docker cmd output: %s", cmd) - return utils.check_cmd("docker exec {name} {cmd}".format( - name=self.name, - cmd=cmd - )) + return utils.check_cmd(f"docker exec {self.name} {cmd}") def create_ns_cmd(self, cmd): - return "nsenter -t {pid} -u -i -p -n {cmd}".format( - pid=self.pid, - cmd=cmd - ) + return f"nsenter -t {self.pid} -u -i -p -n {cmd}" def ns_cmd(self, cmd, wait): - args = "nsenter -t {pid} -u -i -p -n {cmd}".format( - pid=self.pid, - cmd=cmd - ) + args = f"nsenter -t {self.pid} -u -i -p -n {cmd}" return utils.check_cmd(args, wait=wait) def get_pid(self): - args = "docker inspect -f '{{{{.State.Pid}}}}' {name}".format(name=self.name) + args = f"docker inspect -f '{{{{.State.Pid}}}}' {self.name}" output = self.run(args) self.pid = output logging.debug("node(%s) pid: %s", self.name, self.pid) return output def copy_file(self, source, destination): - args = "docker cp {source} {name}:{destination}".format( - source=source, - name=self.name, - destination=destination - ) + args = f"docker cp {source} {self.name}:{destination}" return self.run(args) @@ -185,7 +165,7 @@ class DockerNode(CoreNode): :param str sh: shell to execute command in :return: str """ - return "docker exec -it {name} bash".format(name=self.name) + return f"docker exec -it {self.name} bash" def privatedir(self, path): """ @@ -195,7 +175,7 @@ class DockerNode(CoreNode): :return: nothing """ logging.debug("creating node dir: %s", path) - args = "mkdir -p {path}".format(path=path) + args = f"mkdir -p {path}" self.node_net_cmd(args) def mount(self, source, target): @@ -226,13 +206,13 @@ class DockerNode(CoreNode): temp.close() if directory: - self.node_net_cmd("mkdir -m %o -p %s" % (0o755, directory)) + self.node_net_cmd(f"mkdir -m {0o755:o} -p {directory}") if self.server is not None: self.server.remote_put(temp.name, temp.name) self.client.copy_file(temp.name, filename) - self.node_net_cmd("chmod %o %s" % (mode, filename)) + self.node_net_cmd(f"chmod {mode:o} {filename}") if self.server is not None: - self.net_cmd("rm -f %s" % temp.name) + self.net_cmd(f"rm -f {temp.name}") os.unlink(temp.name) logging.debug( "node(%s) added file: %s; mode: 0%o", self.name, filename, mode @@ -252,7 +232,7 @@ class DockerNode(CoreNode): "node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode ) directory = os.path.dirname(filename) - self.node_net_cmd("mkdir -p %s" % directory) + self.node_net_cmd(f"mkdir -p {directory}") if self.server is None: source = srcfilename @@ -262,4 +242,4 @@ class DockerNode(CoreNode): self.server.remote_put(source, temp.name) self.client.copy_file(source, filename) - self.node_net_cmd("chmod %o %s" % (mode, filename)) + self.node_net_cmd(f"chmod {mode:o} {filename}") diff --git a/daemon/core/nodes/interface.py b/daemon/core/nodes/interface.py index a6e04eb5..c8841432 100644 --- a/daemon/core/nodes/interface.py +++ b/daemon/core/nodes/interface.py @@ -4,7 +4,6 @@ virtual ethernet classes that implement the interfaces available under Linux. import logging import time -from builtins import int, range from core import utils from core.errors import CoreCommandError @@ -345,7 +344,7 @@ class TunTap(CoreInterface): if r == 0: result = True break - msg = "attempt %s failed with nonzero exit status %s" % (i, r) + msg = f"attempt {i} failed with nonzero exit status {r}" if i < attempts + 1: msg += ", retrying..." logging.info(msg) @@ -481,7 +480,7 @@ class GreTap(CoreInterface): self.id = _id sessionid = self.session.short_session_id() # interface name on the local host machine - self.localname = "gt.%s.%s" % (self.id, sessionid) + self.localname = f"gt.{self.id}.{sessionid}" self.transport_type = "raw" if not start: self.up = False diff --git a/daemon/core/nodes/ipaddress.py b/daemon/core/nodes/ipaddress.py index c7860dbc..df2309ab 100644 --- a/daemon/core/nodes/ipaddress.py +++ b/daemon/core/nodes/ipaddress.py @@ -6,7 +6,6 @@ import logging import random import socket import struct -from builtins import bytes, int, range from socket import AF_INET, AF_INET6 @@ -30,7 +29,7 @@ class MacAddress(object): :return: string representation :rtype: str """ - return ":".join("%02x" % x for x in bytearray(self.addr)) + return ":".join(f"{x:02x}" for x in bytearray(self.addr)) def to_link_local(self): """ @@ -218,14 +217,14 @@ class IpPrefix(object): # prefixstr format: address/prefixlen tmp = prefixstr.split("/") if len(tmp) > 2: - raise ValueError("invalid prefix: %s" % prefixstr) + raise ValueError(f"invalid prefix: {prefixstr}") self.af = af if self.af == AF_INET: self.addrlen = 32 elif self.af == AF_INET6: self.addrlen = 128 else: - raise ValueError("invalid address family: %s" % self.af) + raise ValueError(f"invalid address family: {self.af}") if len(tmp) == 2: self.prefixlen = int(tmp[1]) else: @@ -248,7 +247,8 @@ class IpPrefix(object): :return: string representation :rtype: str """ - return "%s/%s" % (socket.inet_ntop(self.af, self.prefix), self.prefixlen) + address = socket.inet_ntop(self.af, self.prefix) + return f"{address}/{self.prefixlen}" def __eq__(self, other): """ @@ -284,7 +284,7 @@ class IpPrefix(object): return NotImplemented a = IpAddress(self.af, self.prefix) + (tmp << (self.addrlen - self.prefixlen)) - prefixstr = "%s/%s" % (a, self.prefixlen) + prefixstr = f"{a}/{self.prefixlen}" if self.__class__ == IpPrefix: return self.__class__(self.af, prefixstr) else: @@ -325,7 +325,7 @@ class IpPrefix(object): self.af == AF_INET and tmp == (1 << (self.addrlen - self.prefixlen)) - 1 ) ): - raise ValueError("invalid hostid for prefix %s: %s" % (self, hostid)) + raise ValueError(f"invalid hostid for prefix {self}: {hostid}") addr = bytes(b"") prefix_endpoint = -1 @@ -375,7 +375,7 @@ class IpPrefix(object): :return: prefix string :rtype: str """ - return "%s" % socket.inet_ntop(self.af, self.prefix) + return socket.inet_ntop(self.af, self.prefix) def netmask_str(self): """ diff --git a/daemon/core/nodes/lxd.py b/daemon/core/nodes/lxd.py index b11086e7..323b20a9 100644 --- a/daemon/core/nodes/lxd.py +++ b/daemon/core/nodes/lxd.py @@ -18,19 +18,17 @@ class LxdClient(object): self.pid = None def create_container(self): - self.run("lxc launch {image} {name}".format(name=self.name, image=self.image)) + self.run(f"lxc launch {self.image} {self.name}") data = self.get_info() self.pid = data["state"]["pid"] return self.pid def get_info(self): - args = "lxc list {name} --format json".format(name=self.name) + args = f"lxc list {self.name} --format json" output = self.run(args) data = json.loads(output) if not data: - raise CoreCommandError( - -1, args, "LXC({name}) not present".format(name=self.name) - ) + raise CoreCommandError(-1, args, f"LXC({self.name}) not present") return data[0] def is_alive(self): @@ -41,13 +39,13 @@ class LxdClient(object): return False def stop_container(self): - self.run("lxc delete --force {name}".format(name=self.name)) + self.run(f"lxc delete --force {self.name}") def create_cmd(self, cmd): - return "lxc exec -nT {name} -- {cmd}".format(name=self.name, cmd=cmd) + return f"lxc exec -nT {self.name} -- {cmd}" def create_ns_cmd(self, cmd): - return "nsenter -t {pid} -m -u -i -p -n {cmd}".format(pid=self.pid, cmd=cmd) + return f"nsenter -t {self.pid} -m -u -i -p -n {cmd}" def check_cmd(self, cmd, wait=True): args = self.create_cmd(cmd) @@ -57,9 +55,7 @@ class LxdClient(object): if destination[0] != "/": destination = os.path.join("/root/", destination) - args = "lxc file push {source} {name}/{destination}".format( - source=source, name=self.name, destination=destination - ) + args = f"lxc file push {source} {self.name}/{destination}" self.run(args) @@ -142,7 +138,7 @@ class LxcNode(CoreNode): :param str sh: shell to execute command in :return: str """ - return "lxc exec {name} -- {sh}".format(name=self.name, sh=sh) + return f"lxc exec {self.name} -- {sh}" def privatedir(self, path): """ @@ -152,7 +148,7 @@ class LxcNode(CoreNode): :return: nothing """ logging.info("creating node dir: %s", path) - args = "mkdir -p {path}".format(path=path) + args = f"mkdir -p {path}" return self.node_net_cmd(args) def mount(self, source, target): @@ -184,13 +180,13 @@ class LxcNode(CoreNode): temp.close() if directory: - self.node_net_cmd("mkdir -m %o -p %s" % (0o755, directory)) + self.node_net_cmd(f"mkdir -m {0o755:o} -p {directory}") if self.server is not None: self.server.remote_put(temp.name, temp.name) self.client.copy_file(temp.name, filename) - self.node_net_cmd("chmod %o %s" % (mode, filename)) + self.node_net_cmd(f"chmod {mode:o} {filename}") if self.server is not None: - self.net_cmd("rm -f %s" % temp.name) + self.net_cmd(f"rm -f {temp.name}") os.unlink(temp.name) logging.debug("node(%s) added file: %s; mode: 0%o", self.name, filename, mode) @@ -208,7 +204,7 @@ class LxcNode(CoreNode): "node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode ) directory = os.path.dirname(filename) - self.node_net_cmd("mkdir -p %s" % directory) + self.node_net_cmd(f"mkdir -p {directory}") if self.server is None: source = srcfilename @@ -218,7 +214,7 @@ class LxcNode(CoreNode): self.server.remote_put(source, temp.name) self.client.copy_file(source, filename) - self.node_net_cmd("chmod %o %s" % (mode, filename)) + self.node_net_cmd(f"chmod {mode:o} {filename}") def addnetif(self, netif, ifindex): super(LxcNode, self).addnetif(netif, ifindex) diff --git a/daemon/core/nodes/netclient.py b/daemon/core/nodes/netclient.py index 9234bef5..beff4e8e 100644 --- a/daemon/core/nodes/netclient.py +++ b/daemon/core/nodes/netclient.py @@ -41,7 +41,7 @@ class LinuxNetClient(object): :param str name: name for hostname :return: nothing """ - self.run("hostname %s" % name) + self.run(f"hostname {name}") def create_route(self, route, device): """ @@ -51,7 +51,7 @@ class LinuxNetClient(object): :param str device: device to add route to :return: nothing """ - self.run("%s route add %s dev %s" % (IP_BIN, route, device)) + self.run(f"{IP_BIN} route add {route} dev {device}") def device_up(self, device): """ @@ -60,7 +60,7 @@ class LinuxNetClient(object): :param str device: device to bring up :return: nothing """ - self.run("%s link set %s up" % (IP_BIN, device)) + self.run(f"{IP_BIN} link set {device} up") def device_down(self, device): """ @@ -69,7 +69,7 @@ class LinuxNetClient(object): :param str device: device to bring down :return: nothing """ - self.run("%s link set %s down" % (IP_BIN, device)) + self.run(f"{IP_BIN} link set {device} down") def device_name(self, device, name): """ @@ -79,7 +79,7 @@ class LinuxNetClient(object): :param str name: name to set :return: nothing """ - self.run("%s link set %s name %s" % (IP_BIN, device, name)) + self.run(f"{IP_BIN} link set {device} name {name}") def device_show(self, device): """ @@ -89,7 +89,27 @@ class LinuxNetClient(object): :return: device information :rtype: str """ - return self.run("%s link show %s" % (IP_BIN, device)) + return self.run(f"{IP_BIN} link show {device}") + + def get_mac(self, device): + """ + Retrieve MAC address for a given device. + + :param str device: device to get mac for + :return: MAC address + :rtype: str + """ + return self.run(f"cat /sys/class/net/{device}/address") + + def get_ifindex(self, device): + """ + Retrieve ifindex for a given device. + + :param str device: device to get ifindex for + :return: ifindex + :rtype: str + """ + return self.run(f"cat /sys/class/net/{device}/ifindex") def device_ns(self, device, namespace): """ @@ -99,7 +119,7 @@ class LinuxNetClient(object): :param str namespace: namespace to set device to :return: nothing """ - self.run("%s link set %s netns %s" % (IP_BIN, device, namespace)) + self.run(f"{IP_BIN} link set {device} netns {namespace}") def device_flush(self, device): """ @@ -108,7 +128,7 @@ class LinuxNetClient(object): :param str device: device to flush :return: nothing """ - self.run("%s -6 address flush dev %s" % (IP_BIN, device)) + self.run(f"{IP_BIN} -6 address flush dev {device}") def device_mac(self, device, mac): """ @@ -118,7 +138,7 @@ class LinuxNetClient(object): :param str mac: mac to set :return: nothing """ - self.run("%s link set dev %s address %s" % (IP_BIN, device, mac)) + self.run(f"{IP_BIN} link set dev {device} address {mac}") def delete_device(self, device): """ @@ -127,7 +147,7 @@ class LinuxNetClient(object): :param str device: device to delete :return: nothing """ - self.run("%s link delete %s" % (IP_BIN, device)) + self.run(f"{IP_BIN} link delete {device}") def delete_tc(self, device): """ @@ -136,7 +156,7 @@ class LinuxNetClient(object): :param str device: device to remove tc :return: nothing """ - self.run("%s qdisc delete dev %s root" % (TC_BIN, device)) + self.run(f"{TC_BIN} qdisc delete dev {device} root") def checksums_off(self, interface_name): """ @@ -145,7 +165,7 @@ class LinuxNetClient(object): :param str interface_name: interface to update :return: nothing """ - self.run("%s -K %s rx off tx off" % (ETHTOOL_BIN, interface_name)) + self.run(f"{ETHTOOL_BIN} -K {interface_name} rx off tx off") def create_address(self, device, address, broadcast=None): """ @@ -158,11 +178,10 @@ class LinuxNetClient(object): """ if broadcast is not None: self.run( - "%s address add %s broadcast %s dev %s" - % (IP_BIN, address, broadcast, device) + f"{IP_BIN} address add {address} broadcast {broadcast} dev {device}" ) else: - self.run("%s address add %s dev %s" % (IP_BIN, address, device)) + self.run(f"{IP_BIN} address add {address} dev {device}") def delete_address(self, device, address): """ @@ -172,7 +191,7 @@ class LinuxNetClient(object): :param str address: address to remove :return: nothing """ - self.run("%s address delete %s dev %s" % (IP_BIN, address, device)) + self.run(f"{IP_BIN} address delete {address} dev {device}") def create_veth(self, name, peer): """ @@ -182,7 +201,7 @@ class LinuxNetClient(object): :param str peer: peer name :return: nothing """ - self.run("%s link add name %s type veth peer name %s" % (IP_BIN, name, peer)) + self.run(f"{IP_BIN} link add name {name} type veth peer name {peer}") def create_gretap(self, device, address, local, ttl, key): """ @@ -195,13 +214,13 @@ class LinuxNetClient(object): :param int key: key for tap :return: nothing """ - cmd = "%s link add %s type gretap remote %s" % (IP_BIN, device, address) + cmd = f"{IP_BIN} link add {device} type gretap remote {address}" if local is not None: - cmd += " local %s" % local + cmd += f" local {local}" if ttl is not None: - cmd += " ttl %s" % ttl + cmd += f" ttl {ttl}" if key is not None: - cmd += " key %s" % key + cmd += f" key {key}" self.run(cmd) def create_bridge(self, name): @@ -211,13 +230,13 @@ class LinuxNetClient(object): :param str name: bridge name :return: nothing """ - self.run("%s addbr %s" % (BRCTL_BIN, name)) - self.run("%s stp %s off" % (BRCTL_BIN, name)) - self.run("%s setfd %s 0" % (BRCTL_BIN, name)) + self.run(f"{BRCTL_BIN} addbr {name}") + self.run(f"{BRCTL_BIN} stp {name} off") + self.run(f"{BRCTL_BIN} setfd {name} 0") self.device_up(name) # turn off multicast snooping so forwarding occurs w/o IGMP joins - snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % name + snoop = f"/sys/devices/virtual/net/{name}/bridge/multicast_snooping" if os.path.exists(snoop): with open(snoop, "w") as f: f.write("0") @@ -230,7 +249,7 @@ class LinuxNetClient(object): :return: nothing """ self.device_down(name) - self.run("%s delbr %s" % (BRCTL_BIN, name)) + self.run(f"{BRCTL_BIN} delbr {name}") def create_interface(self, bridge_name, interface_name): """ @@ -240,7 +259,7 @@ class LinuxNetClient(object): :param str interface_name: interface name :return: nothing """ - self.run("%s addif %s %s" % (BRCTL_BIN, bridge_name, interface_name)) + self.run(f"{BRCTL_BIN} addif {bridge_name} {interface_name}") self.device_up(interface_name) def delete_interface(self, bridge_name, interface_name): @@ -251,7 +270,7 @@ class LinuxNetClient(object): :param str interface_name: interface name :return: nothing """ - self.run("%s delif %s %s" % (BRCTL_BIN, bridge_name, interface_name)) + self.run(f"{BRCTL_BIN} delif {bridge_name} {interface_name}") def existing_bridges(self, _id): """ @@ -259,7 +278,7 @@ class LinuxNetClient(object): :param _id: node id to check bridges for """ - output = self.run("%s show" % BRCTL_BIN) + output = self.run(f"{BRCTL_BIN} show") lines = output.split("\n") for line in lines[1:]: columns = line.split() @@ -278,7 +297,7 @@ class LinuxNetClient(object): :param str name: bridge name :return: nothing """ - self.run("%s setageing %s 0" % (BRCTL_BIN, name)) + self.run(f"{BRCTL_BIN} setageing {name} 0") class OvsNetClient(LinuxNetClient): @@ -293,10 +312,10 @@ class OvsNetClient(LinuxNetClient): :param str name: bridge name :return: nothing """ - self.run("%s add-br %s" % (OVS_BIN, name)) - self.run("%s set bridge %s stp_enable=false" % (OVS_BIN, name)) - self.run("%s set bridge %s other_config:stp-max-age=6" % (OVS_BIN, name)) - self.run("%s set bridge %s other_config:stp-forward-delay=4" % (OVS_BIN, name)) + self.run(f"{OVS_BIN} add-br {name}") + self.run(f"{OVS_BIN} set bridge {name} stp_enable=false") + self.run(f"{OVS_BIN} set bridge {name} other_config:stp-max-age=6") + self.run(f"{OVS_BIN} set bridge {name} other_config:stp-forward-delay=4") self.device_up(name) def delete_bridge(self, name): @@ -307,7 +326,7 @@ class OvsNetClient(LinuxNetClient): :return: nothing """ self.device_down(name) - self.run("%s del-br %s" % (OVS_BIN, name)) + self.run(f"{OVS_BIN} del-br {name}") def create_interface(self, bridge_name, interface_name): """ @@ -317,7 +336,7 @@ class OvsNetClient(LinuxNetClient): :param str interface_name: interface name :return: nothing """ - self.run("%s add-port %s %s" % (OVS_BIN, bridge_name, interface_name)) + self.run(f"{OVS_BIN} add-port {bridge_name} {interface_name}") self.device_up(interface_name) def delete_interface(self, bridge_name, interface_name): @@ -328,7 +347,7 @@ class OvsNetClient(LinuxNetClient): :param str interface_name: interface name :return: nothing """ - self.run("%s del-port %s %s" % (OVS_BIN, bridge_name, interface_name)) + self.run(f"{OVS_BIN} del-port {bridge_name} {interface_name}") def existing_bridges(self, _id): """ @@ -336,7 +355,7 @@ class OvsNetClient(LinuxNetClient): :param _id: node id to check bridges for """ - output = self.run("%s list-br" % OVS_BIN) + output = self.run(f"{OVS_BIN} list-br") if output: for line in output.split("\n"): fields = line.split(".") @@ -351,4 +370,4 @@ class OvsNetClient(LinuxNetClient): :param str name: bridge name :return: nothing """ - self.run("%s set bridge %s other_config:mac-aging-time=0" % (OVS_BIN, name)) + self.run(f"{OVS_BIN} set bridge {name} other_config:mac-aging-time=0") diff --git a/daemon/core/nodes/network.py b/daemon/core/nodes/network.py index 98bec198..229005c4 100644 --- a/daemon/core/nodes/network.py +++ b/daemon/core/nodes/network.py @@ -97,7 +97,7 @@ class EbtablesQueue(object): :return: ebtable atomic command :rtype: list[str] """ - return "%s --atomic-file %s %s" % (EBTABLES_BIN, self.atomic_file, cmd) + return f"{EBTABLES_BIN} --atomic-file {self.atomic_file} {cmd}" def lastupdate(self, wlan): """ @@ -175,7 +175,7 @@ class EbtablesQueue(object): wlan.net_cmd(args) try: - wlan.net_cmd("rm -f %s" % self.atomic_file) + wlan.net_cmd(f"rm -f {self.atomic_file}") except CoreCommandError: logging.exception("error removing atomic file: %s", self.atomic_file) @@ -198,26 +198,22 @@ class EbtablesQueue(object): """ with wlan._linked_lock: # flush the chain - self.cmds.append("-F %s" % wlan.brname) + self.cmds.append(f"-F {wlan.brname}") # rebuild the chain for netif1, v in wlan._linked.items(): for netif2, linked in v.items(): if wlan.policy == "DROP" and linked: self.cmds.extend( [ - "-A %s -i %s -o %s -j ACCEPT" - % (wlan.brname, netif1.localname, netif2.localname), - "-A %s -o %s -i %s -j ACCEPT" - % (wlan.brname, netif1.localname, netif2.localname), + f"-A {wlan.brname} -i {netif1.localname} -o {netif2.localname} -j ACCEPT", + f"-A {wlan.brname} -o {netif1.localname} -i {netif2.localname} -j ACCEPT", ] ) elif wlan.policy == "ACCEPT" and not linked: self.cmds.extend( [ - "-A %s -i %s -o %s -j DROP" - % (wlan.brname, netif1.localname, netif2.localname), - "-A %s -o %s -i %s -j DROP" - % (wlan.brname, netif1.localname, netif2.localname), + f"-A {wlan.brname} -i {netif1.localname} -o {netif2.localname} -j DROP", + f"-A {wlan.brname} -o {netif1.localname} -i {netif2.localname} -j DROP", ] ) @@ -268,7 +264,7 @@ class CoreNetwork(CoreNetworkBase): self.policy = policy self.name = name sessionid = self.session.short_session_id() - self.brname = "b.%s.%s" % (str(self.id), sessionid) + self.brname = f"b.{self.id}.{sessionid}" self.up = False if start: self.startup() @@ -303,9 +299,8 @@ class CoreNetwork(CoreNetworkBase): # create a new ebtables chain for this bridge cmds = [ - "%s -N %s -P %s" % (EBTABLES_BIN, self.brname, self.policy), - "%s -A FORWARD --logical-in %s -j %s" - % (EBTABLES_BIN, self.brname, self.brname), + f"{EBTABLES_BIN} -N {self.brname} -P {self.policy}", + f"{EBTABLES_BIN} -A FORWARD --logical-in {self.brname} -j {self.brname}", ] ebtablescmds(self.net_cmd, cmds) @@ -325,9 +320,8 @@ class CoreNetwork(CoreNetworkBase): try: self.net_client.delete_bridge(self.brname) cmds = [ - "%s -D FORWARD --logical-in %s -j %s" - % (EBTABLES_BIN, self.brname, self.brname), - "%s -X %s" % (EBTABLES_BIN, self.brname), + f"{EBTABLES_BIN} -D FORWARD --logical-in {self.brname} -j {self.brname}", + f"{EBTABLES_BIN} -X {self.brname}", ] ebtablescmds(self.net_cmd, cmds) except CoreCommandError: @@ -379,10 +373,10 @@ class CoreNetwork(CoreNetworkBase): """ # check if the network interfaces are attached to this network if self._netif[netif1.netifi] != netif1: - raise ValueError("inconsistency for netif %s" % netif1.name) + raise ValueError(f"inconsistency for netif {netif1.name}") if self._netif[netif2.netifi] != netif2: - raise ValueError("inconsistency for netif %s" % netif2.name) + raise ValueError(f"inconsistency for netif {netif2.name}") try: linked = self._linked[netif1][netif2] @@ -392,7 +386,7 @@ class CoreNetwork(CoreNetworkBase): elif self.policy == "DROP": linked = False else: - raise Exception("unknown policy: %s" % self.policy) + raise Exception(f"unknown policy: {self.policy}") self._linked[netif1][netif2] = linked return linked @@ -455,7 +449,7 @@ class CoreNetwork(CoreNetworkBase): """ if devname is None: devname = netif.localname - tc = "%s qdisc replace dev %s" % (TC_BIN, devname) + tc = f"{TC_BIN} qdisc replace dev {devname}" parent = "root" changed = False if netif.setparam("bw", bw): @@ -464,16 +458,16 @@ class CoreNetwork(CoreNetworkBase): burst = max(2 * netif.mtu, bw / 1000) # max IP payload limit = 0xFFFF - tbf = "tbf rate %s burst %s limit %s" % (bw, burst, limit) + tbf = f"tbf rate {bw} burst {burst} limit {limit}" if bw > 0: if self.up: - cmd = "%s %s handle 1: %s" % (tc, parent, tbf) + cmd = f"{tc} {parent} handle 1: {tbf}" netif.net_cmd(cmd) netif.setparam("has_tbf", True) changed = True elif netif.getparam("has_tbf") and bw <= 0: if self.up: - cmd = "%s qdisc delete dev %s %s" % (TC_BIN, devname, parent) + cmd = f"{TC_BIN} qdisc delete dev {devname} {parent}" netif.net_cmd(cmd) netif.setparam("has_tbf", False) # removing the parent removes the child @@ -494,17 +488,17 @@ class CoreNetwork(CoreNetworkBase): return # jitter and delay use the same delay statement if delay is not None: - netem += " delay %sus" % delay + netem += f" delay {delay}us" if jitter is not None: if delay is None: - netem += " delay 0us %sus 25%%" % jitter + netem += f" delay 0us {jitter}us 25%" else: - netem += " %sus 25%%" % jitter + netem += f" {jitter}us 25%" if loss is not None and loss > 0: - netem += " loss %s%%" % min(loss, 100) + netem += f" loss {min(loss, 100)}%" if duplicate is not None and duplicate > 0: - netem += " duplicate %s%%" % min(duplicate, 100) + netem += f" duplicate {min(duplicate, 100)}%" delay_check = delay is None or delay <= 0 jitter_check = jitter is None or jitter <= 0 @@ -515,16 +509,13 @@ class CoreNetwork(CoreNetworkBase): if not netif.getparam("has_netem"): return if self.up: - cmd = "%s qdisc delete dev %s %s handle 10:" % (TC_BIN, devname, parent) + cmd = f"{TC_BIN} qdisc delete dev {devname} {parent} handle 10:" netif.net_cmd(cmd) netif.setparam("has_netem", False) elif len(netem) > 1: if self.up: - cmd = "%s qdisc replace dev %s %s handle 10: %s" % ( - TC_BIN, - devname, - parent, - netem, + cmd = ( + f"{TC_BIN} qdisc replace dev {devname} {parent} handle 10: {netem}" ) netif.net_cmd(cmd) netif.setparam("has_netem", True) @@ -540,22 +531,22 @@ class CoreNetwork(CoreNetworkBase): """ sessionid = self.session.short_session_id() try: - _id = "%x" % self.id + _id = f"{self.id:x}" except TypeError: - _id = "%s" % self.id + _id = str(self.id) try: - net_id = "%x" % net.id + net_id = f"{net.id:x}" except TypeError: - net_id = "%s" % net.id + net_id = str(net.id) - localname = "veth%s.%s.%s" % (_id, net_id, sessionid) + localname = f"veth{_id}.{net_id}.{sessionid}" if len(localname) >= 16: - raise ValueError("interface local name %s too long" % localname) + raise ValueError(f"interface local name {localname} too long") - name = "veth%s.%s.%s" % (net_id, _id, sessionid) + name = f"veth{net_id}.{_id}.{sessionid}" if len(name) >= 16: - raise ValueError("interface name %s too long" % name) + raise ValueError(f"interface name {name} too long") netif = Veth(self.session, None, name, localname, start=self.up) self.attach(netif) @@ -689,7 +680,7 @@ class GreTapBridge(CoreNetwork): :return: nothing """ if self.gretap: - raise ValueError("gretap already exists for %s" % self.name) + raise ValueError(f"gretap already exists for {self.name}") remoteip = addrlist[0].split("/")[0] localip = None if len(addrlist) > 1: @@ -773,14 +764,14 @@ class CtrlNet(CoreNetwork): :return: """ use_ovs = self.session.options.get_config("ovs") == "True" - current = "%s/%s" % (address, self.prefix.prefixlen) + current = f"{address}/{self.prefix.prefixlen}" net_client = get_net_client(use_ovs, utils.check_cmd) net_client.create_address(self.brname, current) servers = self.session.distributed.servers for name in servers: server = servers[name] address -= 1 - current = "%s/%s" % (address, self.prefix.prefixlen) + current = f"{address}/{self.prefix.prefixlen}" net_client = get_net_client(use_ovs, server.remote_cmd) net_client.create_address(self.brname, current) @@ -792,7 +783,7 @@ class CtrlNet(CoreNetwork): :raises CoreCommandError: when there is a command exception """ if self.net_client.existing_bridges(self.id): - raise CoreError("old bridges exist for node: %s" % self.id) + raise CoreError(f"old bridges exist for node: {self.id}") CoreNetwork.startup(self) @@ -811,7 +802,7 @@ class CtrlNet(CoreNetwork): self.brname, self.updown_script, ) - self.net_cmd("%s %s startup" % (self.updown_script, self.brname)) + self.net_cmd(f"{self.updown_script} {self.brname} startup") if self.serverintf: self.net_client.create_interface(self.brname, self.serverintf) @@ -839,7 +830,7 @@ class CtrlNet(CoreNetwork): self.brname, self.updown_script, ) - self.net_cmd("%s %s shutdown" % (self.updown_script, self.brname)) + self.net_cmd(f"{self.updown_script} {self.brname} shutdown") except CoreCommandError: logging.exception("error issuing shutdown script shutdown") diff --git a/daemon/core/nodes/physical.py b/daemon/core/nodes/physical.py index 0f9e0217..cae3f298 100644 --- a/daemon/core/nodes/physical.py +++ b/daemon/core/nodes/physical.py @@ -94,7 +94,7 @@ class PhysicalNode(CoreNodeBase): the emulation, no new interface is created; instead, adopt the GreTap netif as the node interface. """ - netif.name = "gt%d" % ifindex + netif.name = f"gt{ifindex}" netif.node = self self.addnetif(netif, ifindex) @@ -161,7 +161,7 @@ class PhysicalNode(CoreNodeBase): ifindex = self.newifindex() if ifname is None: - ifname = "gt%d" % ifindex + ifname = f"gt{ifindex}" if self.up: # this is reached when this node is linked to a network node @@ -177,7 +177,7 @@ class PhysicalNode(CoreNodeBase): def privatedir(self, path): if path[0] != "/": - raise ValueError("path not fully qualified: %s" % path) + raise ValueError(f"path not fully qualified: {path}") hostpath = os.path.join( self.nodedir, os.path.normpath(path).strip("/").replace("/", ".") ) @@ -188,13 +188,13 @@ class PhysicalNode(CoreNodeBase): source = os.path.abspath(source) logging.info("mounting %s at %s", source, target) os.makedirs(target) - self.net_cmd("%s --bind %s %s" % (MOUNT_BIN, source, target), cwd=self.nodedir) + self.net_cmd(f"{MOUNT_BIN} --bind {source} {target}", cwd=self.nodedir) self._mounts.append((source, target)) def umount(self, target): - logging.info("unmounting '%s'" % target) + logging.info("unmounting '%s'", target) try: - self.net_cmd("%s -l %s" % (UMOUNT_BIN, target), cwd=self.nodedir) + self.net_cmd(f"{UMOUNT_BIN} -l {target}", cwd=self.nodedir) except CoreCommandError: logging.exception("unmounting failed for %s", target) @@ -363,7 +363,7 @@ class Rj45Node(CoreNodeBase, CoreInterface): if ifindex == self.ifindex: self.shutdown() else: - raise ValueError("ifindex %s does not exist" % ifindex) + raise ValueError(f"ifindex {ifindex} does not exist") def netif(self, ifindex, net=None): """ @@ -442,7 +442,7 @@ class Rj45Node(CoreNodeBase, CoreInterface): if len(items) < 2: continue - if items[1] == "%s:" % self.localname: + if items[1] == f"{self.localname}:": flags = items[2][1:-1].split(",") if "UP" in flags: self.old_up = True diff --git a/daemon/core/plugins/sdt.py b/daemon/core/plugins/sdt.py index 52635da3..280a2bc2 100644 --- a/daemon/core/plugins/sdt.py +++ b/daemon/core/plugins/sdt.py @@ -4,10 +4,10 @@ sdt.py: Scripted Display Tool (SDT3D) helper import logging import socket - -from future.moves.urllib.parse import urlparse +from urllib.parse import urlparse from core import constants +from core.constants import CORE_DATA_DIR from core.emane.nodes import EmaneNet from core.emulator.enumerations import ( EventTypes, @@ -162,7 +162,7 @@ class Sdt(object): return False self.seturl() - logging.info("connecting to SDT at %s://%s" % (self.protocol, self.address)) + logging.info("connecting to SDT at %s://%s", self.protocol, self.address) if self.sock is None: try: if self.protocol.lower() == "udp": @@ -193,14 +193,14 @@ class Sdt(object): :return: initialize command status :rtype: bool """ - if not self.cmd('path "%s/icons/normal"' % constants.CORE_DATA_DIR): + if not self.cmd(f'path "{CORE_DATA_DIR}/icons/normal"'): return False # send node type to icon mappings for node_type, icon in self.DEFAULT_SPRITES: - if not self.cmd("sprite %s image %s" % (node_type, icon)): + if not self.cmd(f"sprite {node_type} image {icon}"): return False lat, long = self.session.location.refgeo[:2] - return self.cmd("flyto %.6f,%.6f,%d" % (long, lat, self.DEFAULT_ALT)) + return self.cmd(f"flyto {long:.6f},{lat:.6f},{self.DEFAULT_ALT}") def disconnect(self): """ @@ -241,8 +241,8 @@ class Sdt(object): if self.sock is None: return False try: - logging.info("sdt: %s" % cmdstr) - self.sock.sendall("%s\n" % cmdstr) + logging.info("sdt: %s", cmdstr) + self.sock.sendall(f"{cmdstr}\n") return True except IOError: logging.exception("SDT connection error") @@ -267,23 +267,21 @@ class Sdt(object): if not self.connect(): return if flags & MessageFlags.DELETE.value: - self.cmd("delete node,%d" % nodenum) + self.cmd(f"delete node,{nodenum}") return if x is None or y is None: return lat, lon, alt = self.session.location.getgeo(x, y, z) - pos = "pos %.6f,%.6f,%.6f" % (lon, lat, alt) + pos = f"pos {lon:.6f},{lat:.6f},{alt:.6f}" if flags & MessageFlags.ADD.value: if icon is not None: node_type = name icon = icon.replace("$CORE_DATA_DIR", constants.CORE_DATA_DIR) icon = icon.replace("$CORE_CONF_DIR", constants.CORE_CONF_DIR) - self.cmd("sprite %s image %s" % (type, icon)) - self.cmd( - 'node %d type %s label on,"%s" %s' % (nodenum, node_type, name, pos) - ) + self.cmd(f"sprite {node_type} image {icon}") + self.cmd(f'node {nodenum} type {node_type} label on,"{name}" {pos}') else: - self.cmd("node %d %s" % (nodenum, pos)) + self.cmd(f"node {nodenum} {pos}") def updatenodegeo(self, nodenum, lat, long, alt): """ @@ -299,8 +297,8 @@ class Sdt(object): # TODO: received Node Message with lat/long/alt. if not self.connect(): return - pos = "pos %.6f,%.6f,%.6f" % (long, lat, alt) - self.cmd("node %d %s" % (nodenum, pos)) + pos = f"pos {long:.6f},{lat:.6f},{alt:.6f}" + self.cmd(f"node {nodenum} {pos}") def updatelink(self, node1num, node2num, flags, wireless=False): """ @@ -317,14 +315,13 @@ class Sdt(object): if not self.connect(): return if flags & MessageFlags.DELETE.value: - self.cmd("delete link,%s,%s" % (node1num, node2num)) + self.cmd(f"delete link,{node1num},{node2num}") elif flags & MessageFlags.ADD.value: - attr = "" if wireless: attr = " line green,2" else: attr = " line red,2" - self.cmd("link %s,%s%s" % (node1num, node2num, attr)) + self.cmd(f"link {node1num},{node2num}{attr}") def sendobjs(self): """ diff --git a/daemon/core/services/nrl.py b/daemon/core/services/nrl.py index 23484459..a610f1cc 100644 --- a/daemon/core/services/nrl.py +++ b/daemon/core/services/nrl.py @@ -3,8 +3,6 @@ nrl.py: defines services provided by NRL protolib tools hosted here: http://www.nrl.navy.mil/itd/ncs/products """ -from past.builtins import filter - from core import utils from core.nodes.ipaddress import Ipv4Prefix from core.services.coreservices import CoreService @@ -94,7 +92,7 @@ class NrlNhdp(NrlService): cmd += " -flooding ecds" cmd += " -smfClient %s_smf" % node.name - netifs = filter(lambda x: not getattr(x, "control", False), node.netifs()) + netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs())) if len(netifs) > 0: interfacenames = map(lambda x: x.name, netifs) cmd += " -i " @@ -128,7 +126,7 @@ class NrlSmf(NrlService): cmd = "nrlsmf instance %s_smf" % node.name servicenames = map(lambda x: x.name, node.services) - netifs = filter(lambda x: not getattr(x, "control", False), node.netifs()) + netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs())) if len(netifs) == 0: return "" @@ -218,7 +216,7 @@ class NrlOlsrv2(NrlService): cmd += " -p olsr" - netifs = filter(lambda x: not getattr(x, "control", False), node.netifs()) + netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs())) if len(netifs) > 0: interfacenames = map(lambda x: x.name, netifs) cmd += " -i " @@ -246,7 +244,7 @@ class OlsrOrg(NrlService): Generate the appropriate command-line based on node interfaces. """ cmd = cls.startup[0] - netifs = filter(lambda x: not getattr(x, "control", False), node.netifs()) + netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs())) if len(netifs) > 0: interfacenames = map(lambda x: x.name, netifs) cmd += " -i " diff --git a/daemon/core/services/xorp.py b/daemon/core/services/xorp.py index 812fcf9f..1cd62620 100644 --- a/daemon/core/services/xorp.py +++ b/daemon/core/services/xorp.py @@ -312,13 +312,6 @@ class XorpRipng(XorpService): continue cfg += "\tinterface %s {\n" % ifc.name cfg += "\t vif %s {\n" % ifc.name - # for a in ifc.addrlist: - # if a.find(":") < 0: - # continue - # addr = a.split("/")[0] - # cfg += "\t\taddress %s {\n" % addr - # cfg += "\t\t disable: false\n" - # cfg += "\t\t}\n" cfg += "\t\taddress %s {\n" % ifc.hwaddr.tolinklocal() cfg += "\t\t disable: false\n" cfg += "\t\t}\n" diff --git a/daemon/core/utils.py b/daemon/core/utils.py index 8f8da19c..7d88e355 100644 --- a/daemon/core/utils.py +++ b/daemon/core/utils.py @@ -137,7 +137,7 @@ def which(command, required): break if found_path is None and required: - raise ValueError("failed to find required executable(%s) in path" % command) + raise ValueError(f"failed to find required executable({command}) in path") return found_path @@ -238,12 +238,13 @@ def hex_dump(s, bytes_per_word=2, words_per_line=8): line = s[:total_bytes] s = s[total_bytes:] tmp = map( - lambda x: ("%02x" * bytes_per_word) % x, + lambda x: (f"{bytes_per_word:02x}" * bytes_per_word) % x, zip(*[iter(map(ord, line))] * bytes_per_word), ) if len(line) % 2: - tmp.append("%x" % ord(line[-1])) - dump += "0x%08x: %s\n" % (count, " ".join(tmp)) + tmp.append(f"{ord(line[-1]):x}") + tmp = " ".join(tmp) + dump += f"0x{count:08x}: {tmp}\n" count += len(line) return dump[:-1] @@ -261,9 +262,9 @@ def file_munge(pathname, header, text): file_demunge(pathname, header) with open(pathname, "a") as append_file: - append_file.write("# BEGIN %s\n" % header) + append_file.write(f"# BEGIN {header}\n") append_file.write(text) - append_file.write("# END %s\n" % header) + append_file.write(f"# END {header}\n") def file_demunge(pathname, header): @@ -281,9 +282,9 @@ def file_demunge(pathname, header): end = None for i, line in enumerate(lines): - if line == "# BEGIN %s\n" % header: + if line == f"# BEGIN {header}\n": start = i - elif line == "# END %s\n" % header: + elif line == f"# END {header}\n": end = i + 1 if start is None or end is None: @@ -305,7 +306,7 @@ def expand_corepath(pathname, session=None, node=None): :rtype: str """ if session is not None: - pathname = pathname.replace("~", "/home/%s" % session.user) + pathname = pathname.replace("~", f"/home/{session.user}") pathname = pathname.replace("%SESSION%", str(session.id)) pathname = pathname.replace("%SESSION_DIR%", session.session_dir) pathname = pathname.replace("%SESSION_USER%", session.user) @@ -364,7 +365,7 @@ def load_classes(path, clazz): # validate path exists logging.debug("attempting to load modules from path: %s", path) if not os.path.isdir(path): - logging.warning("invalid custom module directory specified" ": %s" % path) + logging.warning("invalid custom module directory specified" ": %s", path) # check if path is in sys.path parent_path = os.path.dirname(path) if parent_path not in sys.path: @@ -380,7 +381,7 @@ def load_classes(path, clazz): # import and add all service modules in the path classes = [] for module_name in module_names: - import_statement = "%s.%s" % (base_module, module_name) + import_statement = f"{base_module}.{module_name}" logging.debug("importing custom module: %s", import_statement) try: module = importlib.import_module(import_statement) diff --git a/daemon/core/xml/corexml.py b/daemon/core/xml/corexml.py index 78d1c488..f4a360c6 100644 --- a/daemon/core/xml/corexml.py +++ b/daemon/core/xml/corexml.py @@ -600,7 +600,7 @@ class CoreXmlReader(object): name = hook.get("name") state = hook.get("state") data = hook.text - hook_type = "hook:%s" % state + hook_type = f"hook:{state}" logging.info("reading hook: state(%s) name(%s)", state, name) self.session.set_hook( hook_type, file_name=name, source_name=None, data=data diff --git a/daemon/core/xml/corexmldeployment.py b/daemon/core/xml/corexmldeployment.py index 0a81b75e..239bace2 100644 --- a/daemon/core/xml/corexmldeployment.py +++ b/daemon/core/xml/corexmldeployment.py @@ -31,20 +31,20 @@ def add_emane_interface(host_element, netif, platform_name="p1", transport_name= host_id = host_element.get("id") # platform data - platform_id = "%s/%s" % (host_id, platform_name) + platform_id = f"{host_id}/{platform_name}" platform_element = etree.SubElement( host_element, "emanePlatform", id=platform_id, name=platform_name ) # transport data - transport_id = "%s/%s" % (host_id, transport_name) + transport_id = f"{host_id}/{transport_name}" etree.SubElement( platform_element, "transport", id=transport_id, name=transport_name ) # nem data - nem_name = "nem%s" % nem_id - nem_element_id = "%s/%s" % (host_id, nem_name) + nem_name = f"nem{nem_id}" + nem_element_id = f"{host_id}/{nem_name}" nem_element = etree.SubElement( platform_element, "nem", id=nem_element_id, name=nem_name ) @@ -68,7 +68,7 @@ def get_address_type(address): def get_ipv4_addresses(hostname): if hostname == "localhost": addresses = [] - args = "%s -o -f inet address show" % IP_BIN + args = f"{IP_BIN} -o -f inet address show" output = utils.check_cmd(args) for line in output.split(os.linesep): split = line.split() @@ -94,13 +94,12 @@ class CoreXmlDeployment(object): self.add_deployment() def find_device(self, name): - device = self.scenario.find("devices/device[@name='%s']" % name) + device = self.scenario.find(f"devices/device[@name='{name}']") return device def find_interface(self, device, name): interface = self.scenario.find( - "devices/device[@name='%s']/interfaces/interface[@name='%s']" - % (device.name, name) + f"devices/device[@name='{device.name}']/interfaces/interface[@name='{name}']" ) return interface @@ -114,7 +113,8 @@ class CoreXmlDeployment(object): def add_physical_host(self, name): # add host - host_id = "%s/%s" % (self.root.get("id"), name) + root_id = self.root.get("id") + host_id = f"{root_id}/{name}" host_element = etree.SubElement(self.root, "testHost", id=host_id, name=name) # add type element @@ -128,10 +128,11 @@ class CoreXmlDeployment(object): def add_virtual_host(self, physical_host, node): if not isinstance(node, CoreNodeBase): - raise TypeError("invalid node type: %s" % node) + raise TypeError(f"invalid node type: {node}") # create virtual host element - host_id = "%s/%s" % (physical_host.get("id"), node.name) + phys_id = physical_host.get("id") + host_id = f"{phys_id}/{node.name}" host_element = etree.SubElement( physical_host, "testHost", id=host_id, name=node.name ) diff --git a/daemon/core/xml/emanexml.py b/daemon/core/xml/emanexml.py index 41319ea4..c97c176f 100644 --- a/daemon/core/xml/emanexml.py +++ b/daemon/core/xml/emanexml.py @@ -57,8 +57,7 @@ def create_file(xml_element, doc_name, file_path, server=None): :return: nothing """ doctype = ( - '' - % {"doc_name": doc_name} + f'' ) if server is not None: temp = NamedTemporaryFile(delete=False) @@ -208,7 +207,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x node.setnemid(netif, nem_id) macstr = _hwaddr_prefix + ":00:00:" - macstr += "%02X:%02X" % ((nem_id >> 8) & 0xFF, nem_id & 0xFF) + macstr += f"{(nem_id >> 8) & 0xFF:02X}:{nem_id & 0xFF:02X}" netif.sethwaddr(MacAddress.from_string(macstr)) # increment nem id @@ -222,7 +221,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x file_path = os.path.join(emane_manager.session.session_dir, file_name) create_file(platform_element, doc_name, file_path) else: - file_name = "platform%d.xml" % key + file_name = f"platform{key}.xml" file_path = os.path.join(emane_manager.session.session_dir, file_name) linked_node = emane_manager.session.nodes[key] create_file(platform_element, doc_name, file_path, linked_node.server) @@ -290,8 +289,8 @@ def build_transport_xml(emane_manager, node, transport_type): """ transport_element = etree.Element( "transport", - name="%s Transport" % transport_type.capitalize(), - library="trans%s" % transport_type.lower(), + name=f"{transport_type.capitalize()} Transport", + library=f"trans{transport_type.lower()}", ) # add bitrate @@ -330,7 +329,7 @@ def create_phy_xml(emane_model, config, file_path, server): will run on, default is None for localhost :return: nothing """ - phy_element = etree.Element("phy", name="%s PHY" % emane_model.name) + phy_element = etree.Element("phy", name=f"{emane_model.name} PHY") if emane_model.phy_library: phy_element.set("library", emane_model.phy_library) @@ -362,7 +361,7 @@ def create_mac_xml(emane_model, config, file_path, server): raise ValueError("must define emane model library") mac_element = etree.Element( - "mac", name="%s MAC" % emane_model.name, library=emane_model.mac_library + "mac", name=f"{emane_model.name} MAC", library=emane_model.mac_library ) add_configurations( mac_element, emane_model.mac_config, config, emane_model.config_ignore @@ -399,7 +398,7 @@ def create_nem_xml( will run on, default is None for localhost :return: nothing """ - nem_element = etree.Element("nem", name="%s NEM" % emane_model.name) + nem_element = etree.Element("nem", name=f"{emane_model.name} NEM") if is_external(config): nem_element.set("type", "unstructured") else: @@ -450,7 +449,7 @@ def transport_file_name(node_id, transport_type): :param str transport_type: transport type to generate transport file :return: """ - return "n%strans%s.xml" % (node_id, transport_type) + return f"n{node_id}trans{transport_type}.xml" def _basename(emane_model, interface=None): @@ -461,14 +460,14 @@ def _basename(emane_model, interface=None): :return: basename used for file creation :rtype: str """ - name = "n%s" % emane_model.id + name = f"n{emane_model.id}" if interface: node_id = interface.node.id if emane_model.session.emane.getifcconfig(node_id, interface, emane_model.name): name = interface.localname.replace(".", "_") - return "%s%s" % (name, emane_model.name) + return f"{name}{emane_model.name}" def nem_file_name(emane_model, interface=None): @@ -484,7 +483,7 @@ def nem_file_name(emane_model, interface=None): append = "" if interface and interface.transport_type == "raw": append = "_raw" - return "%snem%s.xml" % (basename, append) + return f"{basename}nem{append}.xml" def shim_file_name(emane_model, interface=None): @@ -496,7 +495,8 @@ def shim_file_name(emane_model, interface=None): :return: shim xml filename :rtype: str """ - return "%sshim.xml" % _basename(emane_model, interface) + name = _basename(emane_model, interface) + return f"{name}shim.xml" def mac_file_name(emane_model, interface=None): @@ -508,7 +508,8 @@ def mac_file_name(emane_model, interface=None): :return: mac xml filename :rtype: str """ - return "%smac.xml" % _basename(emane_model, interface) + name = _basename(emane_model, interface) + return f"{name}mac.xml" def phy_file_name(emane_model, interface=None): @@ -520,4 +521,5 @@ def phy_file_name(emane_model, interface=None): :return: phy xml filename :rtype: str """ - return "%sphy.xml" % _basename(emane_model, interface) + name = _basename(emane_model, interface) + return f"{name}phy.xml" diff --git a/daemon/examples/grpc/switch.py b/daemon/examples/grpc/switch.py index 89dc371d..48aa63bc 100644 --- a/daemon/examples/grpc/switch.py +++ b/daemon/examples/grpc/switch.py @@ -1,5 +1,4 @@ import logging -from builtins import range from core.api.grpc import client, core_pb2 diff --git a/daemon/examples/myservices/sample.py b/daemon/examples/myservices/sample.py index d6c111ab..8c6dbe06 100644 --- a/daemon/examples/myservices/sample.py +++ b/daemon/examples/myservices/sample.py @@ -37,7 +37,7 @@ class MyService(CoreService): dependencies = () dirs = () configs = ("myservice1.sh", "myservice2.sh") - startup = ("sh %s" % configs[0], "sh %s" % configs[1]) + startup = tuple(f"sh {x}" for x in configs) validate = () validation_mode = ServiceMode.NON_BLOCKING validation_timer = 5 @@ -81,7 +81,7 @@ class MyService(CoreService): if filename == cls.configs[0]: cfg += "# auto-generated by MyService (sample.py)\n" for ifc in node.netifs(): - cfg += 'echo "Node %s has interface %s"\n' % (node.name, ifc.name) + cfg += f'echo "Node {node.name} has interface {ifc.name}"\n' elif filename == cls.configs[1]: cfg += "echo hello" diff --git a/daemon/examples/python/emane80211.py b/daemon/examples/python/emane80211.py index adf6959b..d77252da 100644 --- a/daemon/examples/python/emane80211.py +++ b/daemon/examples/python/emane80211.py @@ -5,7 +5,6 @@ import datetime import logging import parser -from builtins import range from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emulator.coreemu import CoreEmu @@ -49,12 +48,11 @@ def main(): logging.basicConfig(level=logging.INFO) options = parser.parse_options("emane80211") start = datetime.datetime.now() - print( - "running emane 80211 example: nodes(%s) time(%s)" - % (options.nodes, options.time) + logging.info( + "running emane 80211 example: nodes(%s) time(%s)", options.nodes, options.time ) example(options) - print("elapsed time: %s" % (datetime.datetime.now() - start)) + logging.info("elapsed time: %s", datetime.datetime.now() - start) if __name__ == "__main__" or __name__ == "__builtin__": diff --git a/daemon/examples/python/parser.py b/daemon/examples/python/parser.py index 7bbb0fbc..d9efdab6 100644 --- a/daemon/examples/python/parser.py +++ b/daemon/examples/python/parser.py @@ -6,7 +6,7 @@ DEFAULT_STEP = 1 def parse_options(name): - parser = argparse.ArgumentParser(description="Run %s example" % name) + parser = argparse.ArgumentParser(description=f"Run {name} example") parser.add_argument( "-n", "--nodes", @@ -24,28 +24,9 @@ def parse_options(name): options = parser.parse_args() - # usagestr = "usage: %prog [-h] [options] [args]" - # parser = optparse.OptionParser(usage=usagestr) - # - # parser.add_option("-n", "--nodes", dest="nodes", type=int, default=DEFAULT_NODES, - # help="number of nodes to create in this example") - # - # parser.add_option("-t", "--time", dest="time", type=int, default=DEFAULT_TIME, - # help="example iperf run time in seconds") - - # def usage(msg=None, err=0): - # print - # if msg: - # print "%s\n" % msg - # parser.print_help() - # sys.exit(err) - - # parse command line options - # options, args = parser.parse_args() - if options.nodes < 2: - parser.error("invalid min number of nodes: %s" % options.nodes) + parser.error(f"invalid min number of nodes: {options.nodes}") if options.time < 1: - parser.error("invalid test time: %s" % options.time) + parser.error(f"invalid test time: {options.time}") return options diff --git a/daemon/examples/python/switch.py b/daemon/examples/python/switch.py index e4d0fd02..80257a4a 100644 --- a/daemon/examples/python/switch.py +++ b/daemon/examples/python/switch.py @@ -8,7 +8,6 @@ import datetime import logging import parser -from builtins import range from core.emulator.coreemu import CoreEmu from core.emulator.emudata import IpPrefixes @@ -42,14 +41,12 @@ def example(options): first_node = session.get_node(2) last_node = session.get_node(options.nodes + 1) - print("starting iperf server on node: %s" % first_node.name) + logging.info("starting iperf server on node: %s", first_node.name) first_node.node_net_cmd("iperf -s -D") first_node_address = prefixes.ip4_address(first_node) - print("node %s connecting to %s" % (last_node.name, first_node_address)) - output = last_node.node_net_cmd( - "iperf -t %s -c %s" % (options.time, first_node_address) - ) - print(output) + logging.info("node %s connecting to %s", last_node.name, first_node_address) + output = last_node.node_net_cmd(f"iperf -t {options.time} -c {first_node_address}") + logging.info(output) first_node.node_net_cmd("killall -9 iperf") # shutdown session @@ -60,9 +57,11 @@ def main(): logging.basicConfig(level=logging.INFO) options = parser.parse_options("switch") start = datetime.datetime.now() - print("running switch example: nodes(%s) time(%s)" % (options.nodes, options.time)) + logging.info( + "running switch example: nodes(%s) time(%s)", options.nodes, options.time + ) example(options) - print("elapsed time: %s" % (datetime.datetime.now() - start)) + logging.info("elapsed time: %s", datetime.datetime.now() - start) if __name__ == "__main__": diff --git a/daemon/examples/python/switch_inject.py b/daemon/examples/python/switch_inject.py index ff1ff84b..1b7b634c 100644 --- a/daemon/examples/python/switch_inject.py +++ b/daemon/examples/python/switch_inject.py @@ -5,7 +5,6 @@ # and repeat for minnodes <= n <= maxnodes with a step size of # nodestep import logging -from builtins import range from core.emulator.emudata import IpPrefixes from core.emulator.enumerations import EventTypes, NodeTypes diff --git a/daemon/examples/python/wlan.py b/daemon/examples/python/wlan.py index b16af7cd..9506a35c 100644 --- a/daemon/examples/python/wlan.py +++ b/daemon/examples/python/wlan.py @@ -8,7 +8,6 @@ import datetime import logging import parser -from builtins import range from core.emulator.coreemu import CoreEmu from core.emulator.emudata import IpPrefixes, NodeOptions @@ -46,11 +45,11 @@ def example(options): first_node = session.get_node(2) last_node = session.get_node(options.nodes + 1) - print("starting iperf server on node: %s" % first_node.name) + logging.info("starting iperf server on node: %s", first_node.name) first_node.node_net_cmd("iperf -s -D") address = prefixes.ip4_address(first_node) - print("node %s connecting to %s" % (last_node.name, address)) - last_node.node_net_cmd("iperf -t %s -c %s" % (options.time, address)) + logging.info("node %s connecting to %s", last_node.name, address) + last_node.node_net_cmd(f"iperf -t {options.time} -c {address}") first_node.node_net_cmd("killall -9 iperf") # shutdown session @@ -62,9 +61,11 @@ def main(): options = parser.parse_options("wlan") start = datetime.datetime.now() - print("running wlan example: nodes(%s) time(%s)" % (options.nodes, options.time)) + logging.info( + "running wlan example: nodes(%s) time(%s)", options.nodes, options.time + ) example(options) - print("elapsed time: %s" % (datetime.datetime.now() - start)) + logging.info("elapsed time: %s", datetime.datetime.now() - start) if __name__ == "__main__": diff --git a/daemon/requirements.txt b/daemon/requirements.txt index d9029923..96fe83ca 100644 --- a/daemon/requirements.txt +++ b/daemon/requirements.txt @@ -1,9 +1,6 @@ -configparser==4.0.2 fabric==2.5.0 -future==0.17.1 grpcio==1.23.0 grpcio-tools==1.21.1 invoke==1.3.0 lxml==4.4.1 protobuf==3.9.1 -six==1.12.0 diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 07c6a9a7..6b55c14f 100755 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -17,7 +17,8 @@ from core import constants from core.api.grpc.server import CoreGrpcServer from core.api.tlv.corehandlers import CoreHandler, CoreUdpHandler from core.api.tlv.coreserver import CoreServer, CoreUdpServer -from core.emulator import enumerations +from core.constants import CORE_CONF_DIR, COREDPY_VERSION +from core.emulator.enumerations import CORE_API_PORT from core.utils import close_onexec, load_logging_config @@ -65,12 +66,13 @@ def cored(cfg): sys.exit(1) # initialize grpc api - if cfg["grpc"] == "True": - grpc_server = CoreGrpcServer(server.coreemu) - grpc_address = "%s:%s" % (cfg["grpcaddress"], cfg["grpcport"]) - grpc_thread = threading.Thread(target=grpc_server.listen, args=(grpc_address,)) - grpc_thread.daemon = True - grpc_thread.start() + grpc_server = CoreGrpcServer(server.coreemu) + address_config = cfg["grpcaddress"] + port_config = cfg["grpcport"] + grpc_address = f"{address_config}:{port_config}" + grpc_thread = threading.Thread(target=grpc_server.listen, args=(grpc_address,)) + grpc_thread.daemon = True + grpc_thread.start() # start udp server start_udp(server, address) @@ -91,30 +93,33 @@ def get_merged_config(filename): :rtype: dict """ # these are the defaults used in the config file + default_log = os.path.join(constants.CORE_CONF_DIR, "logging.conf") + default_grpc_port = "50051" + default_threads = "1" + default_address = "localhost" defaults = { - "port": "%d" % enumerations.CORE_API_PORT, - "listenaddr": "localhost", - "numthreads": "1", - "grpcport": "50051", - "grpcaddress": "localhost", - "logfile": os.path.join(constants.CORE_CONF_DIR, "logging.conf") + "port": str(CORE_API_PORT), + "listenaddr": default_address, + "numthreads": default_threads, + "grpcport": default_grpc_port, + "grpcaddress": default_address, + "logfile": default_log } parser = argparse.ArgumentParser( - description="CORE daemon v.%s instantiates Linux network namespace nodes." % constants.COREDPY_VERSION) + description=f"CORE daemon v.{COREDPY_VERSION} instantiates Linux network namespace nodes.") parser.add_argument("-f", "--configfile", dest="configfile", - help="read config from specified file; default = %s" % filename) + help=f"read config from specified file; default = {filename}") parser.add_argument("-p", "--port", dest="port", type=int, - help="port number to listen on; default = %s" % defaults["port"]) + help=f"port number to listen on; default = {CORE_API_PORT}") parser.add_argument("-n", "--numthreads", dest="numthreads", type=int, - help="number of server threads; default = %s" % defaults["numthreads"]) + help=f"number of server threads; default = {default_threads}") parser.add_argument("--ovs", action="store_true", help="enable experimental ovs mode, default is false") - parser.add_argument("--grpc", action="store_true", help="enable grpc api, default is false") parser.add_argument("--grpc-port", dest="grpcport", - help="grpc port to listen on; default %s" % defaults["grpcport"]) + help=f"grpc port to listen on; default {default_grpc_port}") parser.add_argument("--grpc-address", dest="grpcaddress", - help="grpc address to listen on; default %s" % defaults["grpcaddress"]) - parser.add_argument("-l", "--logfile", help="core logging configuration; default %s" % defaults["logfile"]) + help=f"grpc address to listen on; default {default_address}") + parser.add_argument("-l", "--logfile", help=f"core logging configuration; default {default_log}") # parse command line options args = parser.parse_args() @@ -146,7 +151,7 @@ def main(): :return: nothing """ # get a configuration merged from config file and command-line arguments - cfg = get_merged_config("%s/core.conf" % constants.CORE_CONF_DIR) + cfg = get_merged_config(f"{CORE_CONF_DIR}/core.conf") # load logging configuration load_logging_config(cfg["logfile"]) diff --git a/daemon/scripts/core-manage b/daemon/scripts/core-manage index 93247f6f..d9b9de08 100755 --- a/daemon/scripts/core-manage +++ b/daemon/scripts/core-manage @@ -38,7 +38,7 @@ class FileUpdater(object): txt = "Updating" if self.action == "check": txt = "Checking" - sys.stdout.write("%s file: %s\n" % (txt, self.filename)) + sys.stdout.write(f"{txt} file: {self.filename}\n") if self.target == "service": r = self.update_file(fn=self.update_services) @@ -52,9 +52,9 @@ class FileUpdater(object): if not r: txt = "NOT " if self.action == "check": - sys.stdout.write("String %sfound.\n" % txt) + sys.stdout.write(f"String {txt} found.\n") else: - sys.stdout.write("File %supdated.\n" % txt) + sys.stdout.write(f"File {txt} updated.\n") return r @@ -70,7 +70,7 @@ class FileUpdater(object): r = self.update_keyvals(key, vals) if self.action == "check": return r - valstr = "%s" % r + valstr = str(r) return "= ".join([key, valstr]) + "\n" def update_emane_models(self, line): @@ -125,7 +125,7 @@ class FileUpdater(object): else: raise ValueError("unknown target") if not os.path.exists(filename): - raise ValueError("file %s does not exist" % filename) + raise ValueError(f"file {filename} does not exist") return search, filename def update_file(self, fn=None): @@ -187,18 +187,17 @@ class FileUpdater(object): def main(): + actions = ", ".join(FileUpdater.actions) + targets = ", ".join(FileUpdater.targets) usagestr = "usage: %prog [-h] [options] \n" usagestr += "\nHelper tool to add, remove, or check for " usagestr += "services, models, and node types\nin a CORE installation.\n" usagestr += "\nExamples:\n %prog add service newrouting" usagestr += "\n %prog -v check model RfPipe" usagestr += "\n %prog --userpath=\"$HOME/.core\" add nodetype \"{ftp ftp.gif ftp.gif {DefaultRoute FTP} netns {FTP server} }\" \n" - usagestr += "\nArguments:\n should be one of: %s" % \ - ", ".join(FileUpdater.actions) - usagestr += "\n should be one of: %s" % \ - ", ".join(FileUpdater.targets) - usagestr += "\n is the text to %s" % \ - ", ".join(FileUpdater.actions) + usagestr += f"\nArguments:\n should be one of: {actions}" + usagestr += f"\n should be one of: {targets}" + usagestr += f"\n is the text to {actions}" parser = optparse.OptionParser(usage=usagestr) parser.set_defaults(userpath=None, verbose=False, ) @@ -222,14 +221,14 @@ def main(): action = args[0] if action not in FileUpdater.actions: - usage("invalid action %s" % action, 1) + usage(f"invalid action {action}", 1) target = args[1] if target not in FileUpdater.targets: - usage("invalid target %s" % target, 1) + usage(f"invalid target {target}", 1) if target == "nodetype" and not options.userpath: - usage("user path option required for this target (%s)" % target) + usage(f"user path option required for this target ({target})") data = args[2] @@ -237,7 +236,7 @@ def main(): up = FileUpdater(action, target, data, options) r = up.process() except Exception as e: - sys.stderr.write("Exception: %s\n" % e) + sys.stderr.write(f"Exception: {e}\n") sys.exit(1) if not r: sys.exit(1) diff --git a/daemon/scripts/coresendmsg b/daemon/scripts/coresendmsg index c8813f21..c8dccfd7 100755 --- a/daemon/scripts/coresendmsg +++ b/daemon/scripts/coresendmsg @@ -21,9 +21,9 @@ def print_available_tlvs(t, tlv_class): """ Print a TLV list. """ - print("TLVs available for %s message:" % t) + print(f"TLVs available for {t} message:") for tlv in sorted([tlv for tlv in tlv_class.tlv_type_map], key=lambda x: x.name): - print("%s:%s" % (tlv.value, tlv.name)) + print(f"{tlv.value}:{tlv.name}") def print_examples(name): @@ -54,9 +54,9 @@ def print_examples(name): "srcname=\"./test.log\"", "move a test.log file from host to node 2"), ] - print("Example %s invocations:" % name) + print(f"Example {name} invocations:") for cmd, descr in examples: - print(" %s %s\n\t\t%s" % (name, cmd, descr)) + print(f" {name} {cmd}\n\t\t{descr}") def receive_message(sock): @@ -86,11 +86,11 @@ def receive_message(sock): except KeyError: msg = coreapi.CoreMessage(msgflags, msghdr, msgdata) msg.message_type = msgtype - print("unimplemented CORE message type: %s" % msg.type_str()) + print(f"unimplemented CORE message type: {msg.type_str()}") return msg if len(data) > msglen + coreapi.CoreMessage.header_len: - print("received a message of type %d, dropping %d bytes of extra data" \ - % (msgtype, len(data) - (msglen + coreapi.CoreMessage.header_len))) + data_size = len(data) - (msglen + coreapi.CoreMessage.header_len) + print(f"received a message of type {msgtype}, dropping {data_size} bytes of extra data") return msgcls(msgflags, msghdr, msgdata) @@ -132,7 +132,7 @@ def connect_to_session(sock, requested): print("requested session not found!") return False - print("joining session: %s" % session) + print(f"joining session: {session}") tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session) flags = MessageFlags.ADD.value smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata) @@ -147,9 +147,9 @@ def receive_response(sock, opt): print("waiting for response...") msg = receive_message(sock) if msg is None: - print("disconnected from %s:%s" % (opt.address, opt.port)) + print(f"disconnected from {opt.address}:{opt.port}") sys.exit(0) - print("received message: %s" % msg) + print(f"received message: {msg}") def main(): @@ -160,36 +160,36 @@ def main(): flags = [flag.name for flag in MessageFlags] usagestr = "usage: %prog [-h|-H] [options] [message-type] [flags=flags] " usagestr += "[message-TLVs]\n\n" - usagestr += "Supported message types:\n %s\n" % types - usagestr += "Supported message flags (flags=f1,f2,...):\n %s" % flags + usagestr += f"Supported message types:\n {types}\n" + usagestr += f"Supported message flags (flags=f1,f2,...):\n {flags}" parser = optparse.OptionParser(usage=usagestr) + default_address = "localhost" + default_session = None + default_tcp = False parser.set_defaults( port=CORE_API_PORT, - address="localhost", - session=None, + address=default_address, + session=default_session, listen=False, examples=False, tlvs=False, - tcp=False + tcp=default_tcp ) parser.add_option("-H", dest="examples", action="store_true", help="show example usage help message and exit") parser.add_option("-p", "--port", dest="port", type=int, - help="TCP port to connect to, default: %d" % \ - parser.defaults["port"]) + help=f"TCP port to connect to, default: {CORE_API_PORT}") parser.add_option("-a", "--address", dest="address", type=str, - help="Address to connect to, default: %s" % \ - parser.defaults["address"]) + help=f"Address to connect to, default: {default_address}") parser.add_option("-s", "--session", dest="session", type=str, - help="Session to join, default: %s" % \ - parser.defaults["session"]) + help=f"Session to join, default: {default_session}") parser.add_option("-l", "--listen", dest="listen", action="store_true", help="Listen for a response message and print it.") parser.add_option("-t", "--list-tlvs", dest="tlvs", action="store_true", help="List TLVs for the specified message type.") parser.add_option("--tcp", dest="tcp", action="store_true", - help="Use TCP instead of UDP and connect to a session default: %s" % parser.defaults["tcp"]) + help=f"Use TCP instead of UDP and connect to a session default: {default_tcp}") def usage(msg=None, err=0): sys.stdout.write("\n") @@ -209,7 +209,7 @@ def main(): # given a message type t, determine the message and TLV classes t = args.pop(0) if t not in types: - usage("Unknown message type requested: %s" % t) + usage(f"Unknown message type requested: {t}") message_type = MessageTypes[t] msg_cls = coreapi.CLASS_MAP[message_type.value] tlv_cls = msg_cls.tlv_class @@ -225,7 +225,7 @@ def main(): for a in args: typevalue = a.split("=") if len(typevalue) < 2: - usage("Use \"type=value\" syntax instead of \"%s\"." % a) + usage(f"Use \"type=value\" syntax instead of \"{a}\".") tlv_typestr = typevalue[0] tlv_valstr = "=".join(typevalue[1:]) if tlv_typestr == "flags": @@ -237,7 +237,7 @@ def main(): tlv_type = tlv_cls.tlv_type_map[tlv_name] tlvdata += tlv_cls.pack_string(tlv_type.value, tlv_valstr) except KeyError: - usage("Unknown TLV: \"%s\"" % tlv_name) + usage(f"Unknown TLV: \"{tlv_name}\"") flags = 0 for f in flagstr.split(","): @@ -249,7 +249,7 @@ def main(): n = flag_enum.value flags |= n except KeyError: - usage("Invalid flag \"%s\"." % f) + usage(f"Invalid flag \"{f}\".") msg = msg_cls.pack(flags, tlvdata) @@ -264,7 +264,7 @@ def main(): try: sock.connect((opt.address, opt.port)) except Exception as e: - print("Error connecting to %s:%s:\n\t%s" % (opt.address, opt.port, e)) + print(f"Error connecting to {opt.address}:{opt.port}:\n\t{e}") sys.exit(1) if opt.tcp and not connect_to_session(sock, opt.session): diff --git a/daemon/setup.py.in b/daemon/setup.py.in index 3a451fb4..378912d3 100644 --- a/daemon/setup.py.in +++ b/daemon/setup.py.in @@ -34,18 +34,12 @@ setup( version="@PACKAGE_VERSION@", packages=find_packages(), install_requires=[ - "configparser", "fabric", - "future", "grpcio", "invoke", "lxml", "protobuf", ], - extra_require={ - ":python_version<'3.2'": ["futures"], - ":python_version<'3.4'": ["enum34"], - }, tests_require=[ "pytest", "mock", diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index ead3c2b4..521a2432 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -67,11 +67,7 @@ class CoreServerTest(object): self.request_handler.handle_message(message) # add broker server for distributed core - distributed = "%s:%s:%s" % ( - self.distributed_server, - distributed_address, - self.port, - ) + distributed = f"{self.distributed_server}:{distributed_address}:{self.port}" message = CoreConfMessage.create( 0, [ diff --git a/daemon/tests/distributed/test_distributed.py b/daemon/tests/distributed/test_distributed.py index 49271d64..7078d6ed 100644 --- a/daemon/tests/distributed/test_distributed.py +++ b/daemon/tests/distributed/test_distributed.py @@ -206,7 +206,7 @@ class TestDistributed: # test a ping command node_one = cored.session.get_node(1) - message = command_message(node_one, "ping -c 5 %s" % ip4_address) + message = command_message(node_one, f"ping -c 5 {ip4_address}") cored.request_handler.dispatch_replies = validate_response cored.request_handler.handle_message(message) @@ -259,7 +259,7 @@ class TestDistributed: # test a ping command node_one = cored.session.get_node(1) - message = command_message(node_one, "ping -c 5 %s" % ip4_address) + message = command_message(node_one, f"ping -c 5 {ip4_address}") cored.request_handler.dispatch_replies = validate_response cored.request_handler.handle_message(message) @@ -307,7 +307,7 @@ class TestDistributed: # test a ping command node_one = cored.session.get_node(1) - message = command_message(node_one, "ping -c 5 %s" % ip4_address) + message = command_message(node_one, f"ping -c 5 {ip4_address}") cored.request_handler.dispatch_replies = validate_response cored.request_handler.handle_message(message) cored.request_handler.handle_message(message) diff --git a/daemon/tests/emane/test_emane.py b/daemon/tests/emane/test_emane.py index 65065665..a0ae05d1 100644 --- a/daemon/tests/emane/test_emane.py +++ b/daemon/tests/emane/test_emane.py @@ -27,7 +27,7 @@ _DIR = os.path.dirname(os.path.abspath(__file__)) def ping(from_node, to_node, ip_prefixes, count=3): address = ip_prefixes.ip4_address(to_node) try: - from_node.node_net_cmd("ping -c %s %s" % (count, address)) + from_node.node_net_cmd(f"ping -c {count} {address}") status = 0 except CoreCommandError as e: status = e.returncode diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 3fc90da8..fa2adc6e 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -20,7 +20,7 @@ _WIRED = [NodeTypes.PEER_TO_PEER, NodeTypes.HUB, NodeTypes.SWITCH] def ping(from_node, to_node, ip_prefixes): address = ip_prefixes.ip4_address(to_node) try: - from_node.node_net_cmd("ping -c 3 %s" % address) + from_node.node_net_cmd(f"ping -c 3 {address}") status = 0 except CoreCommandError as e: status = e.returncode diff --git a/daemon/tests/test_grpc.py b/daemon/tests/test_grpc.py index f9604229..b2ea73ca 100644 --- a/daemon/tests/test_grpc.py +++ b/daemon/tests/test_grpc.py @@ -1,5 +1,4 @@ import time -from builtins import int from queue import Queue import grpc @@ -207,8 +206,7 @@ class TestGrpc: # then assert response.node.id == node.id - @pytest.mark.parametrize("node_id, expected", [(1, True), (2, False)]) - def test_edit_node(self, grpc_server, node_id, expected): + def test_edit_node(self, grpc_server): # given client = CoreGrpcClient() session = grpc_server.coreemu.create_session() @@ -218,13 +216,12 @@ class TestGrpc: x, y = 10, 10 with client.context_connect(): position = core_pb2.Position(x=x, y=y) - response = client.edit_node(session.id, node_id, position) + response = client.edit_node(session.id, node.id, position) # then - assert response.result is expected - if expected is True: - assert node.position.x == x - assert node.position.y == y + assert response.result is True + assert node.position.x == x + assert node.position.y == y @pytest.mark.parametrize("node_id, expected", [(1, True), (2, False)]) def test_delete_node(self, grpc_server, node_id, expected): @@ -254,7 +251,7 @@ class TestGrpc: output = "hello world" # then - command = "echo %s" % output + command = f"echo {output}" with client.context_connect(): response = client.node_command(session.id, node.id, command) @@ -864,7 +861,7 @@ class TestGrpc: client.events(session.id, handle_event) time.sleep(0.1) event = EventData( - event_type=EventTypes.RUNTIME_STATE.value, time="%s" % time.time() + event_type=EventTypes.RUNTIME_STATE.value, time=str(time.time()) ) session.broadcast_event(event) diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index c07e2bd3..40c025ee 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -29,7 +29,7 @@ from core.nodes.ipaddress import Ipv4Prefix def dict_to_str(values): - return "|".join("%s=%s" % (x, values[x]) for x in values) + return "|".join(f"{x}={values[x]}" for x in values) class TestGui: @@ -383,7 +383,7 @@ class TestGui: message = coreapi.CoreFileMessage.create( MessageFlags.ADD.value, [ - (FileTlvs.TYPE, "hook:%s" % state), + (FileTlvs.TYPE, f"hook:{state}"), (FileTlvs.NAME, file_name), (FileTlvs.DATA, file_data), ], @@ -406,7 +406,7 @@ class TestGui: MessageFlags.ADD.value, [ (FileTlvs.NODE, node.id), - (FileTlvs.TYPE, "service:%s" % service), + (FileTlvs.TYPE, f"service:{service}"), (FileTlvs.NAME, file_name), (FileTlvs.DATA, file_data), ], @@ -760,7 +760,7 @@ class TestGui: [ (ConfigTlvs.OBJECT, "broker"), (ConfigTlvs.TYPE, ConfigFlags.UPDATE.value), - (ConfigTlvs.VALUES, "%s:%s:%s" % (server, host, port)), + (ConfigTlvs.VALUES, f"{server}:{host}:{port}"), ], ) coreserver.session.distributed.add_server = mock.MagicMock() @@ -844,7 +844,7 @@ class TestGui: (ConfigTlvs.NODE, node.id), (ConfigTlvs.OBJECT, "services"), (ConfigTlvs.TYPE, ConfigFlags.UPDATE.value), - (ConfigTlvs.OPAQUE, "service:%s" % service), + (ConfigTlvs.OPAQUE, f"service:{service}"), (ConfigTlvs.VALUES, dict_to_str(values)), ], ) diff --git a/daemon/tests/test_nodes.py b/daemon/tests/test_nodes.py index 1f18c87e..34c426c5 100644 --- a/daemon/tests/test_nodes.py +++ b/daemon/tests/test_nodes.py @@ -67,4 +67,4 @@ class TestNodes: # then assert node assert node.up - assert utils.check_cmd("brctl show %s" % node.brname) + assert utils.check_cmd(f"brctl show {node.brname}") diff --git a/ns3/Makefile.am b/ns3/Makefile.am index 115a7008..62086e82 100644 --- a/ns3/Makefile.am +++ b/ns3/Makefile.am @@ -9,8 +9,6 @@ if WANT_PYTHON -PYTHONLIBDIR=$(subst site-packages,dist-packages,$(pythondir)) - SETUPPY = setup.py SETUPPYFLAGS = -v @@ -24,15 +22,15 @@ install-exec-hook: $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ --root=/$(DESTDIR) \ --prefix=$(prefix) \ - --install-lib=$(PYTHONLIBDIR) \ + --install-lib=$(pythondir) \ --single-version-externally-managed \ --no-compile # Python package uninstall uninstall-hook: -rm -rf core_ns3.egg-info - -rm -rf $(DESTDIR)/$(PYTHONLIBDIR)/core_ns3-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info - -rm -rf $(DESTDIR)/$(PYTHONLIBDIR)/corens3 + -rm -rf $(DESTDIR)/$(pythondir)/core_ns3-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + -rm -rf $(DESTDIR)/$(pythondir)/corens3 -rm -rf $(DESTDIR)/$(datadir)/corens3 # Python package cleanup