install: updates to support building deb/rpm packages that contain python wheels and install core from a single file, updates to core to install scripts by way of python directly
This commit is contained in:
parent
cd6bb319ad
commit
fcf6f30302
54 changed files with 528 additions and 187 deletions
79
Makefile.am
79
Makefile.am
|
@ -21,6 +21,7 @@ ACLOCAL_AMFLAGS = -I config
|
||||||
|
|
||||||
# extra files to include with distribution tarball
|
# extra files to include with distribution tarball
|
||||||
EXTRA_DIST = bootstrap.sh \
|
EXTRA_DIST = bootstrap.sh \
|
||||||
|
package \
|
||||||
LICENSE \
|
LICENSE \
|
||||||
README.md \
|
README.md \
|
||||||
ASSIGNMENT_OF_COPYRIGHT.pdf \
|
ASSIGNMENT_OF_COPYRIGHT.pdf \
|
||||||
|
@ -47,7 +48,7 @@ fpm -s dir -t deb -n core-distributed \
|
||||||
--description "Common Open Research Emulator Distributed Package" \
|
--description "Common Open Research Emulator Distributed Package" \
|
||||||
--url https://github.com/coreemu/core \
|
--url https://github.com/coreemu/core \
|
||||||
--vendor "$(PACKAGE_VENDOR)" \
|
--vendor "$(PACKAGE_VENDOR)" \
|
||||||
-p core_distributed_VERSION_ARCH.deb \
|
-p core-distributed_VERSION_ARCH.deb \
|
||||||
-v $(PACKAGE_VERSION) \
|
-v $(PACKAGE_VERSION) \
|
||||||
-d "ethtool" \
|
-d "ethtool" \
|
||||||
-d "procps" \
|
-d "procps" \
|
||||||
|
@ -58,7 +59,8 @@ fpm -s dir -t deb -n core-distributed \
|
||||||
-d "libev4" \
|
-d "libev4" \
|
||||||
-d "openssh-server" \
|
-d "openssh-server" \
|
||||||
-d "xterm" \
|
-d "xterm" \
|
||||||
-C $(DESTDIR)
|
netns/vnoded=/usr/bin/ \
|
||||||
|
netns/vcmd=/usr/bin/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define fpm-distributed-rpm =
|
define fpm-distributed-rpm =
|
||||||
|
@ -68,7 +70,7 @@ fpm -s dir -t rpm -n core-distributed \
|
||||||
--description "Common Open Research Emulator Distributed Package" \
|
--description "Common Open Research Emulator Distributed Package" \
|
||||||
--url https://github.com/coreemu/core \
|
--url https://github.com/coreemu/core \
|
||||||
--vendor "$(PACKAGE_VENDOR)" \
|
--vendor "$(PACKAGE_VENDOR)" \
|
||||||
-p core_distributed_VERSION_ARCH.rpm \
|
-p core-distributed_VERSION_ARCH.rpm \
|
||||||
-v $(PACKAGE_VERSION) \
|
-v $(PACKAGE_VERSION) \
|
||||||
-d "ethtool" \
|
-d "ethtool" \
|
||||||
-d "procps-ng" \
|
-d "procps-ng" \
|
||||||
|
@ -79,12 +81,75 @@ fpm -s dir -t rpm -n core-distributed \
|
||||||
-d "net-tools" \
|
-d "net-tools" \
|
||||||
-d "openssh-server" \
|
-d "openssh-server" \
|
||||||
-d "xterm" \
|
-d "xterm" \
|
||||||
-C $(DESTDIR)
|
netns/vnoded=/usr/bin/ \
|
||||||
|
netns/vcmd=/usr/bin/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
.PHONY: fpm-distributed
|
define fpm-rpm =
|
||||||
fpm-distributed: clean-local-fpm
|
fpm -s dir -t rpm -n core \
|
||||||
$(MAKE) -C netns install DESTDIR=$(DESTDIR)
|
-m "$(PACKAGE_MAINTAINERS)" \
|
||||||
|
--license "BSD" \
|
||||||
|
--description "core vnoded/vcmd and system dependencies" \
|
||||||
|
--url https://github.com/coreemu/core \
|
||||||
|
--vendor "$(PACKAGE_VENDOR)" \
|
||||||
|
-p core_VERSION_ARCH.rpm \
|
||||||
|
-v $(PACKAGE_VERSION) \
|
||||||
|
--rpm-init package/core-daemon \
|
||||||
|
--after-install package/after-install.sh \
|
||||||
|
--after-remove package/after-remove.sh \
|
||||||
|
-d "ethtool" \
|
||||||
|
-d "tk" \
|
||||||
|
-d "procps-ng" \
|
||||||
|
-d "bash >= 3.0" \
|
||||||
|
-d "ebtables" \
|
||||||
|
-d "iproute" \
|
||||||
|
-d "libev" \
|
||||||
|
-d "net-tools" \
|
||||||
|
-d "nftables" \
|
||||||
|
netns/vnoded=/usr/bin/ \
|
||||||
|
netns/vcmd=/usr/bin/ \
|
||||||
|
package/etc/core.conf=/etc/core/ \
|
||||||
|
package/etc/logging.conf=/etc/core/ \
|
||||||
|
package/examples=/opt/core/ \
|
||||||
|
daemon/dist/core-$(PACKAGE_VERSION)-py3-none-any.whl=/opt/core/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define fpm-deb =
|
||||||
|
fpm -s dir -t deb -n core \
|
||||||
|
-m "$(PACKAGE_MAINTAINERS)" \
|
||||||
|
--license "BSD" \
|
||||||
|
--description "core vnoded/vcmd and system dependencies" \
|
||||||
|
--url https://github.com/coreemu/core \
|
||||||
|
--vendor "$(PACKAGE_VENDOR)" \
|
||||||
|
-p core_VERSION_ARCH.deb \
|
||||||
|
-v $(PACKAGE_VERSION) \
|
||||||
|
--deb-systemd package/core-daemon.service \
|
||||||
|
--deb-no-default-config-files \
|
||||||
|
--after-install package/after-install.sh \
|
||||||
|
--after-remove package/after-remove.sh \
|
||||||
|
-d "ethtool" \
|
||||||
|
-d "tk" \
|
||||||
|
-d "libtk-img" \
|
||||||
|
-d "procps" \
|
||||||
|
-d "libc6 >= 2.14" \
|
||||||
|
-d "bash >= 3.0" \
|
||||||
|
-d "ebtables" \
|
||||||
|
-d "iproute2" \
|
||||||
|
-d "libev4" \
|
||||||
|
-d "nftables" \
|
||||||
|
netns/vnoded=/usr/bin/ \
|
||||||
|
netns/vcmd=/usr/bin/ \
|
||||||
|
package/etc/core.conf=/etc/core/ \
|
||||||
|
package/etc/logging.conf=/etc/core/ \
|
||||||
|
package/examples=/opt/core/ \
|
||||||
|
daemon/dist/core-$(PACKAGE_VERSION)-py3-none-any.whl=/opt/core/
|
||||||
|
endef
|
||||||
|
|
||||||
|
.PHONY: fpm
|
||||||
|
fpm: clean-local-fpm
|
||||||
|
cd daemon && poetry build -f wheel
|
||||||
|
$(call fpm-deb)
|
||||||
|
$(call fpm-rpm)
|
||||||
$(call fpm-distributed-deb)
|
$(call fpm-distributed-deb)
|
||||||
$(call fpm-distributed-rpm)
|
$(call fpm-distributed-rpm)
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,7 @@ DISTCLEANFILES = Makefile.in
|
||||||
|
|
||||||
# files to include with distribution tarball
|
# files to include with distribution tarball
|
||||||
EXTRA_DIST = core \
|
EXTRA_DIST = core \
|
||||||
data \
|
|
||||||
doc/conf.py.in \
|
doc/conf.py.in \
|
||||||
examples \
|
|
||||||
scripts \
|
|
||||||
tests \
|
tests \
|
||||||
setup.cfg \
|
setup.cfg \
|
||||||
poetry.lock \
|
poetry.lock \
|
||||||
|
|
103
daemon/core/scripts/cleanup.py
Executable file
103
daemon/core/scripts/cleanup.py
Executable file
|
@ -0,0 +1,103 @@
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def check_root() -> None:
|
||||||
|
if os.geteuid() != 0:
|
||||||
|
print("permission denied, run this script as root")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="helps cleanup lingering core processes and files",
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d", "--daemon", action="store_true", help="also kill core-daemon"
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_daemon() -> None:
|
||||||
|
print("killing core-daemon process ... ", end="")
|
||||||
|
result = subprocess.call("pkill -9 core-daemon", shell=True)
|
||||||
|
if result:
|
||||||
|
print("not found")
|
||||||
|
else:
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_nodes() -> None:
|
||||||
|
print("killing vnoded processes ... ", end="")
|
||||||
|
result = subprocess.call("pkill -KILL vnoded", shell=True)
|
||||||
|
if result:
|
||||||
|
print("none found")
|
||||||
|
else:
|
||||||
|
time.sleep(1)
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_emane() -> None:
|
||||||
|
print("killing emane processes ... ", end="")
|
||||||
|
result = subprocess.call("pkill emane", shell=True)
|
||||||
|
if result:
|
||||||
|
print("none found")
|
||||||
|
else:
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_sessions() -> None:
|
||||||
|
print("removing session directories ... ", end="")
|
||||||
|
result = subprocess.call("rm -rf /tmp/pycore*", shell=True)
|
||||||
|
if result:
|
||||||
|
print("none found")
|
||||||
|
else:
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_interfaces() -> None:
|
||||||
|
print("cleaning up devices")
|
||||||
|
output = subprocess.check_output("ip -o -br link show", shell=True)
|
||||||
|
lines = output.decode().strip().split("\n")
|
||||||
|
for line in lines:
|
||||||
|
values = line.split()
|
||||||
|
name = values[0]
|
||||||
|
if (
|
||||||
|
name.startswith("veth")
|
||||||
|
or name.startswith("gt.")
|
||||||
|
or name.startswith("b.")
|
||||||
|
or name.startswith("ctrl")
|
||||||
|
):
|
||||||
|
result = subprocess.call(f"ip link delete {name}", shell=True)
|
||||||
|
if result:
|
||||||
|
print(f"failed to remove {name}")
|
||||||
|
else:
|
||||||
|
print(f"removed {name}")
|
||||||
|
if name.startswith("b."):
|
||||||
|
result = subprocess.call(
|
||||||
|
f"nft delete table bridge {name}",
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
shell=True,
|
||||||
|
)
|
||||||
|
if not result:
|
||||||
|
print(f"cleared nft rules for {name}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
check_root()
|
||||||
|
args = parse_args()
|
||||||
|
if args.daemon:
|
||||||
|
cleanup_daemon()
|
||||||
|
cleanup_nodes()
|
||||||
|
cleanup_emane()
|
||||||
|
cleanup_interfaces()
|
||||||
|
cleanup_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from argparse import (
|
from argparse import (
|
||||||
|
@ -32,7 +31,9 @@ NODE_TYPES = [x.name for x in NodeType if x != NodeType.PEER_TO_PEER]
|
||||||
|
|
||||||
|
|
||||||
def protobuf_to_json(message: Any) -> Dict[str, Any]:
|
def protobuf_to_json(message: Any) -> Dict[str, Any]:
|
||||||
return MessageToDict(message, including_default_value_fields=True, preserving_proto_field_name=True)
|
return MessageToDict(
|
||||||
|
message, including_default_value_fields=True, preserving_proto_field_name=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def print_json(data: Any) -> None:
|
def print_json(data: Any) -> None:
|
||||||
|
@ -122,18 +123,15 @@ def get_current_session(core: CoreGrpcClient, session_id: Optional[int]) -> int:
|
||||||
return sessions[0].id
|
return sessions[0].id
|
||||||
|
|
||||||
|
|
||||||
def create_iface(iface_id: int, mac: str, ip4_net: IPNetwork, ip6_net: IPNetwork) -> Interface:
|
def create_iface(
|
||||||
|
iface_id: int, mac: str, ip4_net: IPNetwork, ip6_net: IPNetwork
|
||||||
|
) -> Interface:
|
||||||
ip4 = str(ip4_net.ip) if ip4_net else None
|
ip4 = str(ip4_net.ip) if ip4_net else None
|
||||||
ip4_mask = ip4_net.prefixlen if ip4_net else None
|
ip4_mask = ip4_net.prefixlen if ip4_net else None
|
||||||
ip6 = str(ip6_net.ip) if ip6_net else None
|
ip6 = str(ip6_net.ip) if ip6_net else None
|
||||||
ip6_mask = ip6_net.prefixlen if ip6_net else None
|
ip6_mask = ip6_net.prefixlen if ip6_net else None
|
||||||
return Interface(
|
return Interface(
|
||||||
id=iface_id,
|
id=iface_id, mac=mac, ip4=ip4, ip4_mask=ip4_mask, ip6=ip6, ip6_mask=ip6_mask
|
||||||
mac=mac,
|
|
||||||
ip4=ip4,
|
|
||||||
ip4_mask=ip4_mask,
|
|
||||||
ip6=ip6,
|
|
||||||
ip6_mask=ip6_mask,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,12 +214,14 @@ def query_session(core: CoreGrpcClient, args: Namespace) -> None:
|
||||||
for node in session.nodes.values():
|
for node in session.nodes.values():
|
||||||
xy_pos = f"{int(node.position.x)},{int(node.position.y)}"
|
xy_pos = f"{int(node.position.x)},{int(node.position.y)}"
|
||||||
geo_pos = f"{node.geo.lon:.7f},{node.geo.lat:.7f},{node.geo.alt:f}"
|
geo_pos = f"{node.geo.lon:.7f},{node.geo.lat:.7f},{node.geo.alt:f}"
|
||||||
print(f"{node.id:<7} | {node.name[:7]:<7} | {node.type.name[:7]:<7} | {xy_pos:<9} | {geo_pos}")
|
print(
|
||||||
|
f"{node.id:<7} | {node.name[:7]:<7} | {node.type.name[:7]:<7} | {xy_pos:<9} | {geo_pos}"
|
||||||
|
)
|
||||||
print("\nLinks")
|
print("\nLinks")
|
||||||
for link in session.links:
|
for link in session.links:
|
||||||
n1 = session.nodes[link.node1_id].name
|
n1 = session.nodes[link.node1_id].name
|
||||||
n2 = session.nodes[link.node2_id].name
|
n2 = session.nodes[link.node2_id].name
|
||||||
print(f"Node | ", end="")
|
print("Node | ", end="")
|
||||||
print_iface_header()
|
print_iface_header()
|
||||||
print(f"{n1:<6} | ", end="")
|
print(f"{n1:<6} | ", end="")
|
||||||
if link.iface1:
|
if link.iface1:
|
||||||
|
@ -248,7 +248,9 @@ def query_node(core: CoreGrpcClient, args: Namespace) -> None:
|
||||||
print("ID | Name | Type | XY | Geo")
|
print("ID | Name | Type | XY | Geo")
|
||||||
xy_pos = f"{int(node.position.x)},{int(node.position.y)}"
|
xy_pos = f"{int(node.position.x)},{int(node.position.y)}"
|
||||||
geo_pos = f"{node.geo.lon:.7f},{node.geo.lat:.7f},{node.geo.alt:f}"
|
geo_pos = f"{node.geo.lon:.7f},{node.geo.lat:.7f},{node.geo.alt:f}"
|
||||||
print(f"{node.id:<7} | {node.name[:7]:<7} | {node.type.name[:7]:<7} | {xy_pos:<9} | {geo_pos}")
|
print(
|
||||||
|
f"{node.id:<7} | {node.name[:7]:<7} | {node.type.name[:7]:<7} | {xy_pos:<9} | {geo_pos}"
|
||||||
|
)
|
||||||
if ifaces:
|
if ifaces:
|
||||||
print("Interfaces")
|
print("Interfaces")
|
||||||
print("Connected To | ", end="")
|
print("Connected To | ", end="")
|
||||||
|
@ -348,10 +350,14 @@ def add_link(core: CoreGrpcClient, args: Namespace) -> None:
|
||||||
session_id = get_current_session(core, args.session)
|
session_id = get_current_session(core, args.session)
|
||||||
iface1 = None
|
iface1 = None
|
||||||
if args.iface1_id is not None:
|
if args.iface1_id is not None:
|
||||||
iface1 = create_iface(args.iface1_id, args.iface1_mac, args.iface1_ip4, args.iface1_ip6)
|
iface1 = create_iface(
|
||||||
|
args.iface1_id, args.iface1_mac, args.iface1_ip4, args.iface1_ip6
|
||||||
|
)
|
||||||
iface2 = None
|
iface2 = None
|
||||||
if args.iface2_id is not None:
|
if args.iface2_id is not None:
|
||||||
iface2 = create_iface(args.iface2_id, args.iface2_mac, args.iface2_ip4, args.iface2_ip6)
|
iface2 = create_iface(
|
||||||
|
args.iface2_id, args.iface2_mac, args.iface2_ip4, args.iface2_ip6
|
||||||
|
)
|
||||||
options = LinkOptions(
|
options = LinkOptions(
|
||||||
bandwidth=args.bandwidth,
|
bandwidth=args.bandwidth,
|
||||||
loss=args.loss,
|
loss=args.loss,
|
||||||
|
@ -432,13 +438,17 @@ def setup_node_parser(parent) -> None:
|
||||||
add_parser.add_argument(
|
add_parser.add_argument(
|
||||||
"-t", "--type", choices=NODE_TYPES, default="DEFAULT", help="type of node"
|
"-t", "--type", choices=NODE_TYPES, default="DEFAULT", help="type of node"
|
||||||
)
|
)
|
||||||
add_parser.add_argument("-m", "--model", help="used to determine services, optional")
|
add_parser.add_argument(
|
||||||
|
"-m", "--model", help="used to determine services, optional"
|
||||||
|
)
|
||||||
group = add_parser.add_mutually_exclusive_group(required=True)
|
group = add_parser.add_mutually_exclusive_group(required=True)
|
||||||
group.add_argument("-p", "--pos", type=position_type, help="x,y position")
|
group.add_argument("-p", "--pos", type=position_type, help="x,y position")
|
||||||
group.add_argument("-g", "--geo", type=geo_type, help="lon,lat,alt position")
|
group.add_argument("-g", "--geo", type=geo_type, help="lon,lat,alt position")
|
||||||
add_parser.add_argument("-ic", "--icon", help="icon to use, optional")
|
add_parser.add_argument("-ic", "--icon", help="icon to use, optional")
|
||||||
add_parser.add_argument("-im", "--image", help="container image, optional")
|
add_parser.add_argument("-im", "--image", help="container image, optional")
|
||||||
add_parser.add_argument("-e", "--emane", help="emane model, only required for emane nodes")
|
add_parser.add_argument(
|
||||||
|
"-e", "--emane", help="emane model, only required for emane nodes"
|
||||||
|
)
|
||||||
add_parser.set_defaults(func=add_node)
|
add_parser.set_defaults(func=add_node)
|
||||||
|
|
||||||
edit_parser = subparsers.add_parser("edit", help="edit a node")
|
edit_parser = subparsers.add_parser("edit", help="edit a node")
|
||||||
|
@ -449,7 +459,9 @@ def setup_node_parser(parent) -> None:
|
||||||
|
|
||||||
move_parser = subparsers.add_parser("move", help="move a node")
|
move_parser = subparsers.add_parser("move", help="move a node")
|
||||||
move_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
move_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
||||||
move_parser.add_argument("-i", "--id", type=int, help="id to use, optional", required=True)
|
move_parser.add_argument(
|
||||||
|
"-i", "--id", type=int, help="id to use, optional", required=True
|
||||||
|
)
|
||||||
group = move_parser.add_mutually_exclusive_group(required=True)
|
group = move_parser.add_mutually_exclusive_group(required=True)
|
||||||
group.add_argument("-p", "--pos", type=position_type, help="x,y position")
|
group.add_argument("-p", "--pos", type=position_type, help="x,y position")
|
||||||
group.add_argument("-g", "--geo", type=geo_type, help="lon,lat,alt position")
|
group.add_argument("-g", "--geo", type=geo_type, help="lon,lat,alt position")
|
||||||
|
@ -474,19 +486,33 @@ def setup_link_parser(parent) -> None:
|
||||||
add_parser.add_argument("-n1", "--node1", type=int, help="node1 id", required=True)
|
add_parser.add_argument("-n1", "--node1", type=int, help="node1 id", required=True)
|
||||||
add_parser.add_argument("-n2", "--node2", type=int, help="node2 id", required=True)
|
add_parser.add_argument("-n2", "--node2", type=int, help="node2 id", required=True)
|
||||||
add_parser.add_argument("-i1-i", "--iface1-id", type=int, help="node1 interface id")
|
add_parser.add_argument("-i1-i", "--iface1-id", type=int, help="node1 interface id")
|
||||||
add_parser.add_argument("-i1-m", "--iface1-mac", type=mac_type, help="node1 interface mac")
|
add_parser.add_argument(
|
||||||
add_parser.add_argument("-i1-4", "--iface1-ip4", type=ip4_type, help="node1 interface ip4")
|
"-i1-m", "--iface1-mac", type=mac_type, help="node1 interface mac"
|
||||||
add_parser.add_argument("-i1-6", "--iface1-ip6", type=ip6_type, help="node1 interface ip6")
|
)
|
||||||
|
add_parser.add_argument(
|
||||||
|
"-i1-4", "--iface1-ip4", type=ip4_type, help="node1 interface ip4"
|
||||||
|
)
|
||||||
|
add_parser.add_argument(
|
||||||
|
"-i1-6", "--iface1-ip6", type=ip6_type, help="node1 interface ip6"
|
||||||
|
)
|
||||||
add_parser.add_argument("-i2-i", "--iface2-id", type=int, help="node2 interface id")
|
add_parser.add_argument("-i2-i", "--iface2-id", type=int, help="node2 interface id")
|
||||||
add_parser.add_argument("-i2-m", "--iface2-mac", type=mac_type, help="node2 interface mac")
|
add_parser.add_argument(
|
||||||
add_parser.add_argument("-i2-4", "--iface2-ip4", type=ip4_type, help="node2 interface ip4")
|
"-i2-m", "--iface2-mac", type=mac_type, help="node2 interface mac"
|
||||||
add_parser.add_argument("-i2-6", "--iface2-ip6", type=ip6_type, help="node2 interface ip6")
|
)
|
||||||
|
add_parser.add_argument(
|
||||||
|
"-i2-4", "--iface2-ip4", type=ip4_type, help="node2 interface ip4"
|
||||||
|
)
|
||||||
|
add_parser.add_argument(
|
||||||
|
"-i2-6", "--iface2-ip6", type=ip6_type, help="node2 interface ip6"
|
||||||
|
)
|
||||||
add_parser.add_argument("-b", "--bandwidth", type=int, help="bandwidth (bps)")
|
add_parser.add_argument("-b", "--bandwidth", type=int, help="bandwidth (bps)")
|
||||||
add_parser.add_argument("-l", "--loss", type=float, help="loss (%%)")
|
add_parser.add_argument("-l", "--loss", type=float, help="loss (%%)")
|
||||||
add_parser.add_argument("-j", "--jitter", type=int, help="jitter (us)")
|
add_parser.add_argument("-j", "--jitter", type=int, help="jitter (us)")
|
||||||
add_parser.add_argument("-de", "--delay", type=int, help="delay (us)")
|
add_parser.add_argument("-de", "--delay", type=int, help="delay (us)")
|
||||||
add_parser.add_argument("-du", "--duplicate", type=int, help="duplicate (%%)")
|
add_parser.add_argument("-du", "--duplicate", type=int, help="duplicate (%%)")
|
||||||
add_parser.add_argument("-u", "--uni", action="store_true", help="is link unidirectional?")
|
add_parser.add_argument(
|
||||||
|
"-u", "--uni", action="store_true", help="is link unidirectional?"
|
||||||
|
)
|
||||||
add_parser.set_defaults(func=add_link)
|
add_parser.set_defaults(func=add_link)
|
||||||
|
|
||||||
edit_parser = subparsers.add_parser("edit", help="edit a link")
|
edit_parser = subparsers.add_parser("edit", help="edit a link")
|
||||||
|
@ -507,8 +533,12 @@ def setup_link_parser(parent) -> None:
|
||||||
|
|
||||||
delete_parser = subparsers.add_parser("delete", help="delete a link")
|
delete_parser = subparsers.add_parser("delete", help="delete a link")
|
||||||
delete_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
delete_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
||||||
delete_parser.add_argument("-n1", "--node1", type=int, help="node1 id", required=True)
|
delete_parser.add_argument(
|
||||||
delete_parser.add_argument("-n2", "--node2", type=int, help="node1 id", required=True)
|
"-n1", "--node1", type=int, help="node1 id", required=True
|
||||||
|
)
|
||||||
|
delete_parser.add_argument(
|
||||||
|
"-n2", "--node2", type=int, help="node1 id", required=True
|
||||||
|
)
|
||||||
delete_parser.add_argument("-i1", "--iface1", type=int, help="node1 interface id")
|
delete_parser.add_argument("-i1", "--iface1", type=int, help="node1 interface id")
|
||||||
delete_parser.add_argument("-i2", "--iface2", type=int, help="node2 interface id")
|
delete_parser.add_argument("-i2", "--iface2", type=int, help="node2 interface id")
|
||||||
delete_parser.set_defaults(func=delete_link)
|
delete_parser.set_defaults(func=delete_link)
|
||||||
|
@ -526,20 +556,28 @@ def setup_query_parser(parent) -> None:
|
||||||
|
|
||||||
session_parser = subparsers.add_parser("session", help="query session")
|
session_parser = subparsers.add_parser("session", help="query session")
|
||||||
session_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
session_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
||||||
session_parser.add_argument("-i", "--id", type=int, help="session to query", required=True)
|
session_parser.add_argument(
|
||||||
|
"-i", "--id", type=int, help="session to query", required=True
|
||||||
|
)
|
||||||
session_parser.set_defaults(func=query_session)
|
session_parser.set_defaults(func=query_session)
|
||||||
|
|
||||||
node_parser = subparsers.add_parser("node", help="query node")
|
node_parser = subparsers.add_parser("node", help="query node")
|
||||||
node_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
node_parser.formatter_class = ArgumentDefaultsHelpFormatter
|
||||||
node_parser.add_argument("-i", "--id", type=int, help="session to query", required=True)
|
node_parser.add_argument(
|
||||||
node_parser.add_argument("-n", "--node", type=int, help="node to query", required=True)
|
"-i", "--id", type=int, help="session to query", required=True
|
||||||
|
)
|
||||||
|
node_parser.add_argument(
|
||||||
|
"-n", "--node", type=int, help="node to query", required=True
|
||||||
|
)
|
||||||
node_parser.set_defaults(func=query_node)
|
node_parser.set_defaults(func=query_node)
|
||||||
|
|
||||||
|
|
||||||
def setup_xml_parser(parent) -> None:
|
def setup_xml_parser(parent) -> None:
|
||||||
parser = parent.add_parser("xml", help="open session xml")
|
parser = parent.add_parser("xml", help="open session xml")
|
||||||
parser.formatter_class = ArgumentDefaultsHelpFormatter
|
parser.formatter_class = ArgumentDefaultsHelpFormatter
|
||||||
parser.add_argument("-f", "--file", type=file_type, help="xml file to open", required=True)
|
parser.add_argument(
|
||||||
|
"-f", "--file", type=file_type, help="xml file to open", required=True
|
||||||
|
)
|
||||||
parser.add_argument("-s", "--start", action="store_true", help="start the session?")
|
parser.add_argument("-s", "--start", action="store_true", help="start the session?")
|
||||||
parser.set_defaults(func=open_xml)
|
parser.set_defaults(func=open_xml)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
"""
|
||||||
core-daemon: the CORE daemon is a server process that receives CORE API
|
core-daemon: the CORE daemon is a server process that receives CORE API
|
||||||
messages and instantiates emulated nodes and networks within the kernel. Various
|
messages and instantiates emulated nodes and networks within the kernel. Various
|
||||||
|
@ -61,18 +60,35 @@ def get_merged_config(filename):
|
||||||
defaults = {
|
defaults = {
|
||||||
"grpcport": default_grpc_port,
|
"grpcport": default_grpc_port,
|
||||||
"grpcaddress": default_address,
|
"grpcaddress": default_address,
|
||||||
"logfile": default_log
|
"logfile": default_log,
|
||||||
}
|
}
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description=f"CORE daemon v.{COREDPY_VERSION} instantiates Linux network namespace nodes.")
|
description=f"CORE daemon v.{COREDPY_VERSION} instantiates Linux network namespace nodes."
|
||||||
parser.add_argument("-f", "--configfile", dest="configfile",
|
)
|
||||||
help=f"read config from specified file; default = {filename}")
|
parser.add_argument(
|
||||||
parser.add_argument("--ovs", action="store_true", help="enable experimental ovs mode, default is false")
|
"-f",
|
||||||
parser.add_argument("--grpc-port", dest="grpcport",
|
"--configfile",
|
||||||
help=f"grpc port to listen on; default {default_grpc_port}")
|
dest="configfile",
|
||||||
parser.add_argument("--grpc-address", dest="grpcaddress",
|
help=f"read config from specified file; default = {filename}",
|
||||||
help=f"grpc address to listen on; default {default_address}")
|
)
|
||||||
parser.add_argument("-l", "--logfile", help=f"core logging configuration; default {default_log}")
|
parser.add_argument(
|
||||||
|
"--ovs",
|
||||||
|
action="store_true",
|
||||||
|
help="enable experimental ovs mode, default is false",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--grpc-port",
|
||||||
|
dest="grpcport",
|
||||||
|
help=f"grpc port to listen on; default {default_grpc_port}",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--grpc-address",
|
||||||
|
dest="grpcaddress",
|
||||||
|
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
|
# parse command line options
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
# convert ovs to internal format
|
# convert ovs to internal format
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import TimedRotatingFileHandler
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
|
@ -9,12 +8,19 @@ from core.gui.app import Application
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
# parse flags
|
# parse flags
|
||||||
parser = argparse.ArgumentParser(description=f"CORE Python GUI")
|
parser = argparse.ArgumentParser(description="CORE Python GUI")
|
||||||
parser.add_argument("-l", "--level", choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], default="INFO",
|
parser.add_argument(
|
||||||
help="logging level")
|
"-l",
|
||||||
|
"--level",
|
||||||
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
||||||
|
default="INFO",
|
||||||
|
help="logging level",
|
||||||
|
)
|
||||||
parser.add_argument("-p", "--proxy", action="store_true", help="enable proxy")
|
parser.add_argument("-p", "--proxy", action="store_true", help="enable proxy")
|
||||||
parser.add_argument("-s", "--session", type=int, help="session id to join")
|
parser.add_argument("-s", "--session", type=int, help="session id to join")
|
||||||
parser.add_argument("--create-dir", action="store_true", help="create gui directory and exit")
|
parser.add_argument(
|
||||||
|
"--create-dir", action="store_true", help="create gui directory and exit"
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# check home directory exists and create if necessary
|
# check home directory exists and create if necessary
|
||||||
|
@ -25,9 +31,13 @@ def main() -> None:
|
||||||
# setup logging
|
# setup logging
|
||||||
log_format = "%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s"
|
log_format = "%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s"
|
||||||
stream_handler = logging.StreamHandler()
|
stream_handler = logging.StreamHandler()
|
||||||
file_handler = TimedRotatingFileHandler(filename=appconfig.LOG_PATH, when="D", backupCount=5)
|
file_handler = TimedRotatingFileHandler(
|
||||||
|
filename=appconfig.LOG_PATH, when="D", backupCount=5
|
||||||
|
)
|
||||||
log_level = logging.getLevelName(args.level)
|
log_level = logging.getLevelName(args.level)
|
||||||
logging.basicConfig(level=log_level, format=log_format, handlers=[stream_handler, file_handler])
|
logging.basicConfig(
|
||||||
|
level=log_level, format=log_format, handlers=[stream_handler, file_handler]
|
||||||
|
)
|
||||||
logging.getLogger("PIL").setLevel(logging.ERROR)
|
logging.getLogger("PIL").setLevel(logging.ERROR)
|
||||||
|
|
||||||
# start app
|
# start app
|
|
@ -1,5 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
@ -31,7 +29,10 @@ def parse_args() -> argparse.Namespace:
|
||||||
"-f", "--file", required=True, type=path_type, help="core file to play"
|
"-f", "--file", required=True, type=path_type, help="core file to play"
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-s", "--session", type=int, help="session to play to, first found session otherwise"
|
"-s",
|
||||||
|
"--session",
|
||||||
|
type=int,
|
||||||
|
help="session to play to, first found session otherwise",
|
||||||
)
|
)
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
import argparse
|
||||||
import enum
|
import enum
|
||||||
import select
|
import select
|
||||||
|
@ -60,15 +59,15 @@ class SdtClient:
|
||||||
|
|
||||||
class RouterMonitor:
|
class RouterMonitor:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
session: int,
|
session: int,
|
||||||
src: str,
|
src: str,
|
||||||
dst: str,
|
dst: str,
|
||||||
pkt: str,
|
pkt: str,
|
||||||
rate: int,
|
rate: int,
|
||||||
dead: int,
|
dead: int,
|
||||||
sdt_host: str,
|
sdt_host: str,
|
||||||
sdt_port: int,
|
sdt_port: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.queue = Queue()
|
self.queue = Queue()
|
||||||
self.core = CoreGrpcClient()
|
self.core = CoreGrpcClient()
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
import argparse
|
||||||
import re
|
import re
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
|
@ -6,9 +5,15 @@ from io import TextIOWrapper
|
||||||
|
|
||||||
def parse_args() -> argparse.Namespace:
|
def parse_args() -> argparse.Namespace:
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description=f"Helps transition older CORE services to work with newer versions")
|
description="Helps transition older CORE services to work with newer versions"
|
||||||
parser.add_argument("-f", "--file", dest="file", type=argparse.FileType("r"),
|
)
|
||||||
help=f"service file to update")
|
parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--file",
|
||||||
|
dest="file",
|
||||||
|
type=argparse.FileType("r"),
|
||||||
|
help="service file to update",
|
||||||
|
)
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,17 +25,32 @@ def update_service(service_file: TextIOWrapper) -> None:
|
||||||
# rename dirs to directories
|
# rename dirs to directories
|
||||||
line = re.sub(r"^(\s+)dirs", r"\1directories", line)
|
line = re.sub(r"^(\s+)dirs", r"\1directories", line)
|
||||||
# fix import states for service
|
# fix import states for service
|
||||||
line = re.sub(r"^.+import.+CoreService.+$",
|
line = re.sub(
|
||||||
r"from core.services.coreservices import CoreService", line)
|
r"^.+import.+CoreService.+$",
|
||||||
|
r"from core.services.coreservices import CoreService",
|
||||||
|
line,
|
||||||
|
)
|
||||||
# fix method signatures
|
# fix method signatures
|
||||||
line = re.sub(r"def generateconfig\(cls, node, filename, services\)",
|
line = re.sub(
|
||||||
r"def generate_config(cls, node, filename)", line)
|
r"def generateconfig\(cls, node, filename, services\)",
|
||||||
line = re.sub(r"def getvalidate\(cls, node, services\)",
|
r"def generate_config(cls, node, filename)",
|
||||||
r"def get_validate(cls, node)", line)
|
line,
|
||||||
line = re.sub(r"def getstartup\(cls, node, services\)",
|
)
|
||||||
r"def get_startup(cls, node)", line)
|
line = re.sub(
|
||||||
line = re.sub(r"def getconfigfilenames\(cls, nodenum, services\)",
|
r"def getvalidate\(cls, node, services\)",
|
||||||
r"def get_configs(cls, node)", line)
|
r"def get_validate(cls, node)",
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
line = re.sub(
|
||||||
|
r"def getstartup\(cls, node, services\)",
|
||||||
|
r"def get_startup(cls, node)",
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
line = re.sub(
|
||||||
|
r"def getconfigfilenames\(cls, nodenum, services\)",
|
||||||
|
r"def get_configs(cls, node)",
|
||||||
|
line,
|
||||||
|
)
|
||||||
# remove unwanted lines
|
# remove unwanted lines
|
||||||
if re.search(r"addservice\(", line):
|
if re.search(r"addservice\(", line):
|
||||||
continue
|
continue
|
|
@ -14,6 +14,14 @@ include = [
|
||||||
]
|
]
|
||||||
exclude = ["core/constants.py.in"]
|
exclude = ["core/constants.py.in"]
|
||||||
|
|
||||||
|
[tool.poetry.scripts]
|
||||||
|
core-daemon = "core.scripts.daemon:main"
|
||||||
|
core-cli = "core.scripts.cli:main"
|
||||||
|
core-gui = "core.scripts.gui:main"
|
||||||
|
core-player = "core.scripts.player:main"
|
||||||
|
core-route-monitor = "core.scripts.routemonitor:main"
|
||||||
|
core-service-update = "core.scripts.serviceupdate:main"
|
||||||
|
core-cleanup = "core.scripts.cleanup:main"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ "z$1" = "z-h" -o "z$1" = "z--help" ]; then
|
|
||||||
echo "usage: $0 [-d [-l]]"
|
|
||||||
echo -n " Clean up all CORE namespaces processes, bridges, interfaces, "
|
|
||||||
echo "and session\n directories. Options:"
|
|
||||||
echo " -h show this help message and exit"
|
|
||||||
echo " -d also kill the Python daemon"
|
|
||||||
echo " -l remove the core-daemon.log file"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ `id -u` != 0 ]; then
|
|
||||||
echo "Permission denied. Re-run this script as root."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
|
|
||||||
export PATH
|
|
||||||
|
|
||||||
if [ "z$1" = "z-d" ]; then
|
|
||||||
pypids=`pidof python3 python`
|
|
||||||
for p in $pypids; do
|
|
||||||
grep -q core-daemon /proc/$p/cmdline
|
|
||||||
if [ $? = 0 ]; then
|
|
||||||
echo "cleaning up core-daemon process: $p"
|
|
||||||
kill -9 $p
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "z$2" = "z-l" ]; then
|
|
||||||
rm -f /var/log/core-daemon.log
|
|
||||||
fi
|
|
||||||
|
|
||||||
kaopts="-v"
|
|
||||||
killall --help 2>&1 | grep -q namespace
|
|
||||||
if [ $? = 0 ]; then
|
|
||||||
kaopts="$kaopts --ns 0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
vnodedpids=`pidof vnoded`
|
|
||||||
if [ "z$vnodedpids" != "z" ]; then
|
|
||||||
echo "cleaning up old vnoded processes: $vnodedpids"
|
|
||||||
killall $kaopts -KILL vnoded
|
|
||||||
# pause for 1 second for interfaces to disappear
|
|
||||||
sleep 1
|
|
||||||
fi
|
|
||||||
killall -q emane
|
|
||||||
killall -q emanetransportd
|
|
||||||
killall -q emaneeventservice
|
|
||||||
|
|
||||||
if [ -d /sys/class/net ]; then
|
|
||||||
ifcommand="ls -1 /sys/class/net"
|
|
||||||
else
|
|
||||||
ifcommand="ip -o link show | sed -r -e 's/[0-9]+: ([^[:space:]]+): .*/\1/'"
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval "$ifcommand" | awk '
|
|
||||||
/^veth[0-9]+\./ {print "removing interface " $1; system("ip link del " $1);}
|
|
||||||
/tmp\./ {print "removing interface " $1; system("ip link del " $1);}
|
|
||||||
/gt\./ {print "removing interface " $1; system("ip link del " $1);}
|
|
||||||
/b\./ {print "removing bridge " $1; system("ip link set " $1 " down; ip link del " $1);}
|
|
||||||
/ctrl[0-9]+\./ {print "removing bridge " $1; system("ip link set " $1 " down; ip link del " $1);}
|
|
||||||
'
|
|
||||||
|
|
||||||
nft list ruleset | awk '
|
|
||||||
$3 ~ /^b\./ {print "removing nftables " $3; system("nft delete table bridge " $3);}
|
|
||||||
'
|
|
||||||
|
|
||||||
rm -rf /tmp/pycore*
|
|
15
package/Dockerfile.centos
Normal file
15
package/Dockerfile.centos
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM centos:7
|
||||||
|
LABEL Description="CORE CentOS Image"
|
||||||
|
|
||||||
|
# define environment
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# install basic dependencies
|
||||||
|
RUN yum update -y && yum install -y python3 python3-pip python3-tkinter
|
||||||
|
RUN python3 -m pip install --upgrade pip
|
||||||
|
|
||||||
|
# install core
|
||||||
|
WORKDIR /opt/core
|
||||||
|
COPY core_*.rpm .
|
||||||
|
RUN NO_VENV=1 yum install -y ./core_*.rpm
|
15
package/Dockerfile.ubuntu
Normal file
15
package/Dockerfile.ubuntu
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM ubuntu:20.04
|
||||||
|
LABEL Description="CORE Docker Ubuntu Image"
|
||||||
|
|
||||||
|
# define environment
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# install basic dependencies
|
||||||
|
RUN apt-get update && apt-get install -y python3 python3-tk python3-pip python3-venv
|
||||||
|
RUN python3 -m pip install --upgrade pip
|
||||||
|
|
||||||
|
# install core
|
||||||
|
WORKDIR /opt/core
|
||||||
|
COPY core_*.deb .
|
||||||
|
RUN apt-get install -y ./core_*.deb
|
16
package/after-install.sh
Normal file
16
package/after-install.sh
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/sh
|
||||||
|
if [ ! -z "${NO_PYTHON}" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
PYTHON="${PYTHON:=python3}"
|
||||||
|
if [ ! -z "${NO_VENV}" ]; then
|
||||||
|
${PYTHON} -m pip install /opt/core/core-*.whl
|
||||||
|
echo "DAEMON=/usr/local/bin/core-daemon" > /opt/core/service
|
||||||
|
else
|
||||||
|
${PYTHON} -m venv /opt/core/venv
|
||||||
|
. /opt/core/venv/bin/activate
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install /opt/core/core-*.whl
|
||||||
|
echo "DAEMON=/opt/core/venv/bin/core-daemon" > /opt/core/service
|
||||||
|
fi
|
13
package/after-remove.sh
Normal file
13
package/after-remove.sh
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
if [ -v NO_PYTHON ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
PYTHON="${PYTHON:=python3}"
|
||||||
|
if [ -v NO_VENV ]; then
|
||||||
|
${PYTHON} -m pip uninstall core
|
||||||
|
else
|
||||||
|
${PYTHON} -m venv /opt/core/venv
|
||||||
|
. /opt/core/venv/bin/activate
|
||||||
|
pip uninstall core
|
||||||
|
fi
|
112
package/core-daemon
Normal file
112
package/core-daemon
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: core-daemon
|
||||||
|
# Required-Start: $network $remote_fs
|
||||||
|
# Required-Stop: $network $remote_fs
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: Start the core-daemon CORE daemon at boot time
|
||||||
|
# Description: Starts and stops the core-daemon CORE daemon used to
|
||||||
|
# provide network emulation services for the CORE GUI
|
||||||
|
# or scripts.
|
||||||
|
### END INIT INFO
|
||||||
|
#
|
||||||
|
# chkconfig: 35 90 03
|
||||||
|
# description: Starts and stops the CORE daemon \
|
||||||
|
# used to provide network emulation services.
|
||||||
|
#
|
||||||
|
# config: /etc/core/
|
||||||
|
|
||||||
|
. /opt/core/service
|
||||||
|
NAME=`basename $0`
|
||||||
|
PIDFILE="/var/$NAME.pid"
|
||||||
|
LOG="/var/log/$NAME.log"
|
||||||
|
CMD="$DAEMON"
|
||||||
|
|
||||||
|
get_pid() {
|
||||||
|
cat "$PIDFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_alive() {
|
||||||
|
[ -f "$PIDFILE" ] && ps -p `get_pid` > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
corestart() {
|
||||||
|
if is_alive; then
|
||||||
|
echo "$NAME already started"
|
||||||
|
else
|
||||||
|
echo "starting $NAME"
|
||||||
|
$CMD 2>&1 >> "$LOG" &
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $! > "$PIDFILE"
|
||||||
|
if ! is_alive; then
|
||||||
|
echo "unable to start $NAME, see $LOG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
corestop() {
|
||||||
|
if is_alive; then
|
||||||
|
echo -n "stopping $NAME.."
|
||||||
|
kill `get_pid`
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
sleep 1
|
||||||
|
if ! is_alive; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo -n "."
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
if is_alive; then
|
||||||
|
echo "not stopped; may still be shutting down"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "stopped"
|
||||||
|
if [ -f "$PIDFILE" ]; then
|
||||||
|
rm -f "$PIDFILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$NAME not running"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
corerestart() {
|
||||||
|
corestop
|
||||||
|
corestart
|
||||||
|
}
|
||||||
|
|
||||||
|
corestatus() {
|
||||||
|
if is_alive; then
|
||||||
|
echo "$NAME is running"
|
||||||
|
else
|
||||||
|
echo "$NAME is stopped"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
corestart
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
corestop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
corerestart
|
||||||
|
;;
|
||||||
|
force-reload)
|
||||||
|
corerestart
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
corestatus
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|status}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
12
package/core-daemon.service
Normal file
12
package/core-daemon.service
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Common Open Research Emulator Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
EnvironmentFile=/opt/core/service
|
||||||
|
ExecStart=$DAEMON
|
||||||
|
TasksMax=infinity
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
0
package/examples/myemane/__init__.py
Normal file
0
package/examples/myemane/__init__.py
Normal file
34
tasks.py
34
tasks.py
|
@ -291,25 +291,6 @@ def install_core_files(c, local=False, verbose=False, prefix=DEFAULT_PREFIX):
|
||||||
hide = not verbose
|
hide = not verbose
|
||||||
python = get_python(c)
|
python = get_python(c)
|
||||||
bin_dir = Path(prefix).joinpath("bin")
|
bin_dir = Path(prefix).joinpath("bin")
|
||||||
# install scripts
|
|
||||||
for script in Path("daemon/scripts").iterdir():
|
|
||||||
dest = bin_dir.joinpath(script.name)
|
|
||||||
with open(script, "r") as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
first = lines[0].strip()
|
|
||||||
# modify python scripts to point to virtual environment
|
|
||||||
if not local and first == "#!/usr/bin/env python3":
|
|
||||||
lines[0] = f"#!{python}\n"
|
|
||||||
temp = NamedTemporaryFile("w", delete=False)
|
|
||||||
for line in lines:
|
|
||||||
temp.write(line)
|
|
||||||
temp.close()
|
|
||||||
c.run(f"sudo cp {temp.name} {dest}", hide=hide)
|
|
||||||
c.run(f"sudo chmod 755 {dest}", hide=hide)
|
|
||||||
os.unlink(temp.name)
|
|
||||||
# copy normal links
|
|
||||||
else:
|
|
||||||
c.run(f"sudo cp {script} {dest}", hide=hide)
|
|
||||||
# setup core python helper
|
# setup core python helper
|
||||||
if not local:
|
if not local:
|
||||||
core_python = bin_dir.joinpath("core-python")
|
core_python = bin_dir.joinpath("core-python")
|
||||||
|
@ -325,12 +306,12 @@ def install_core_files(c, local=False, verbose=False, prefix=DEFAULT_PREFIX):
|
||||||
# install core configuration file
|
# install core configuration file
|
||||||
config_dir = "/etc/core"
|
config_dir = "/etc/core"
|
||||||
c.run(f"sudo mkdir -p {config_dir}", hide=hide)
|
c.run(f"sudo mkdir -p {config_dir}", hide=hide)
|
||||||
c.run(f"sudo cp -n daemon/data/core.conf {config_dir}", hide=hide)
|
c.run(f"sudo cp -n package/etc/core.conf {config_dir}", hide=hide)
|
||||||
c.run(f"sudo cp -n daemon/data/logging.conf {config_dir}", hide=hide)
|
c.run(f"sudo cp -n package/etc/logging.conf {config_dir}", hide=hide)
|
||||||
# install examples
|
# install examples
|
||||||
examples_dir = f"{prefix}/share/core"
|
examples_dir = f"{prefix}/share/core"
|
||||||
c.run(f"sudo mkdir -p {examples_dir}", hide=hide)
|
c.run(f"sudo mkdir -p {examples_dir}", hide=hide)
|
||||||
c.run(f"sudo cp -r daemon/examples {examples_dir}", hide=hide)
|
c.run(f"sudo cp -r package/examples {examples_dir}", hide=hide)
|
||||||
|
|
||||||
|
|
||||||
@task(
|
@task(
|
||||||
|
@ -467,11 +448,9 @@ def uninstall(
|
||||||
c.run("sudo -v", hide=True)
|
c.run("sudo -v", hide=True)
|
||||||
with p.start("uninstalling core"):
|
with p.start("uninstalling core"):
|
||||||
c.run("sudo make uninstall", hide=hide)
|
c.run("sudo make uninstall", hide=hide)
|
||||||
|
|
||||||
with p.start("cleaning build directory"):
|
with p.start("cleaning build directory"):
|
||||||
c.run("make clean", hide=hide)
|
c.run("make clean", hide=hide)
|
||||||
c.run("./bootstrap.sh clean", hide=hide)
|
c.run("./bootstrap.sh clean", hide=hide)
|
||||||
|
|
||||||
if local:
|
if local:
|
||||||
with p.start("uninstalling core"):
|
with p.start("uninstalling core"):
|
||||||
python_bin = get_env_python()
|
python_bin = get_env_python()
|
||||||
|
@ -485,22 +464,15 @@ def uninstall(
|
||||||
c.run("poetry run pre-commit uninstall", hide=hide)
|
c.run("poetry run pre-commit uninstall", hide=hide)
|
||||||
with p.start("uninstalling poetry virtual environment"):
|
with p.start("uninstalling poetry virtual environment"):
|
||||||
c.run(f"poetry env remove {python}", hide=hide)
|
c.run(f"poetry env remove {python}", hide=hide)
|
||||||
|
|
||||||
# remove installed files
|
# remove installed files
|
||||||
bin_dir = Path(prefix).joinpath("bin")
|
bin_dir = Path(prefix).joinpath("bin")
|
||||||
with p.start("uninstalling script files"):
|
|
||||||
for script in Path("daemon/scripts").iterdir():
|
|
||||||
dest = bin_dir.joinpath(script.name)
|
|
||||||
c.run(f"sudo rm -f {dest}", hide=hide)
|
|
||||||
with p.start("uninstalling examples"):
|
with p.start("uninstalling examples"):
|
||||||
examples_dir = Path(prefix).joinpath("share/core")
|
examples_dir = Path(prefix).joinpath("share/core")
|
||||||
c.run(f"sudo rm -rf {examples_dir}")
|
c.run(f"sudo rm -rf {examples_dir}")
|
||||||
|
|
||||||
# remove core-python symlink
|
# remove core-python symlink
|
||||||
if not local:
|
if not local:
|
||||||
core_python = bin_dir.joinpath("core-python")
|
core_python = bin_dir.joinpath("core-python")
|
||||||
c.run(f"sudo rm -f {core_python}", hide=hide)
|
c.run(f"sudo rm -f {core_python}", hide=hide)
|
||||||
|
|
||||||
# remove service
|
# remove service
|
||||||
systemd_dir = Path("/lib/systemd/system/")
|
systemd_dir = Path("/lib/systemd/system/")
|
||||||
service_name = "core-daemon.service"
|
service_name = "core-daemon.service"
|
||||||
|
|
Loading…
Reference in a new issue