Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • jirikalvoda/vm
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (5)
...@@ -7,13 +7,14 @@ import json ...@@ -7,13 +7,14 @@ import json
from dataclasses import dataclass from dataclasses import dataclass
import functools import functools
from typing import Optional from typing import Optional
import traceback
socket_path = '.socket' socket_path = '.socket'
is_daemon = False is_daemon = False
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv)==2 and sys.argv[1]=="server": if len(sys.argv)>=2 and sys.argv[1]=="server":
is_daemon = True is_daemon = True
class S(): class S():
...@@ -316,7 +317,7 @@ def create_from_img(ucred: Ucred, target: str, new_ssh: bool = True, target_name ...@@ -316,7 +317,7 @@ def create_from_img(ucred: Ucred, target: str, new_ssh: bool = True, target_name
mount_dir = target_dir+"mount/" mount_dir = target_dir+"mount/"
os.mkdir(mount_dir) os.mkdir(mount_dir)
r('mount', '-o', 'loop,offset=210763776', '--type', 'ext4', target_dir+'img', mount_dir) r('mount', '-o', 'nosymfollow,loop,offset=210763776', '--type', 'ext4', target_dir+'img', mount_dir)
try: try:
with open(mount_dir+"/etc/hostname", "w") as f: f.write(target_name+"\n") with open(mount_dir+"/etc/hostname", "w") as f: f.write(target_name+"\n")
if new_ssh: if new_ssh:
...@@ -440,7 +441,7 @@ def sshfs(vm: str, user: str = None): ...@@ -440,7 +441,7 @@ def sshfs(vm: str, user: str = None):
if os.path.isdir(mount_dir) and len(os.listdir(mount_dir)) != 0: if os.path.isdir(mount_dir) and len(os.listdir(mount_dir)) != 0:
return return
r("mkdir", "-p", mount_dir) r("mkdir", "-p", mount_dir)
r("sshfs", "-o", "follow_symlinks", f"{user}@{get_ip(vm)}:/", mount_dir, "-o", f"ssh_command=ssh -i {vm_dir(vm)}/id_ed25519 -o UserKnownHostsFile={vm_dir(vm)}/known_hosts -o HostKeyAlgorithms=ssh-ed25519 -o HostKeyAlias=vm_{vm}") r("sshfs", "-o", "transform_symlinks", f"{user}@{get_ip(vm)}:/", mount_dir, "-o", f"ssh_command=ssh -i {vm_dir(vm)}/id_ed25519 -o UserKnownHostsFile={vm_dir(vm)}/known_hosts -o HostKeyAlgorithms=ssh-ed25519 -o HostKeyAlias=vm_{vm}")
if not os.path.islink(mount_dir+'~'): if not os.path.islink(mount_dir+'~'):
home_dir = "/root" if user == "root" else f"/home/{user}" home_dir = "/root" if user == "root" else f"/home/{user}"
r("ln", "-sr", mount_dir+home_dir, mount_dir+"~") r("ln", "-sr", mount_dir+home_dir, mount_dir+"~")
...@@ -458,20 +459,25 @@ def sshfs_clean(): ...@@ -458,20 +459,25 @@ def sshfs_clean():
def escape_sh(*arg): def escape_sh(*arg):
return " ".join("'" + s.replace("'", "'\"'\"'") + "'" for s in arg) return " ".join("'" + s.replace("'", "'\"'\"'") + "'" for s in arg)
def get_vnc_client_env(vm):
vnc_client_env = os.environ.copy()
vnc_client_env["VNC_PASSWORD"] = open(vm_dir(vm)+"vnc_passwd", "r").read().strip()
return vnc_client_env
vncviewer_args = ["-FullscreenSystemKeys=0", "-AcceptClipboard=0", "-SendClipboard=0"]
@cmd @cmd
def vncapp(vm: str, cmd: str, user: str = "u"): def vncapp(vm: str, cmd: str, user: str = "u"):
import random import random
import psutil import psutil
unit_id = random.randint(100000, 999999) unit_id = random.randint(100000, 999999)
vm, user = extended_name(vm, user=user) vm, user = extended_name(vm, user=user)
vm = name_to_id(vm)
display_id=random.randint(10, 50) display_id=random.randint(10, 50)
vnc_server = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncapp-vnc-{display_id}-{unit_id} --user -P bash -c '(cat /vnc_passwd;echo; cat /vnc_passwd; echo;echo n) | vncpasswd; vncserver :{display_id}'", user=user)) vnc_server = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncapp-vnc-{display_id}-{unit_id} --user -P bash -c '(cat /vnc_passwd;echo; cat /vnc_passwd; echo;echo n) | vncpasswd; vncserver :{display_id}'", user=user))
time.sleep(1) time.sleep(1)
vnc_client_env = os.environ.copy()
vnc_client_env["VNC_PASSWORD"] = open(vm_dir(vm)+"vnc_passwd", "r").read().strip()
app = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncapp-app-{display_id}-{unit_id} --user -P -E DISPLAY=:{display_id} bash -c {escape_sh(cmd)}", user=user)); app = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncapp-app-{display_id}-{unit_id} --user -P -E DISPLAY=:{display_id} bash -c {escape_sh(cmd)}", user=user));
vnc_client = subprocess.Popen(["vncviewer", get_ip(vm)+f":{display_id}"], env=vnc_client_env) vnc_client = subprocess.Popen(["vncviewer", get_ip(vm)+f":{display_id}", *vncviewer_args], env=get_vnc_client_env(vm))
def on_terminate(proc): def on_terminate(proc):
if verbose: print(f"KILLING ALL APPS because {proc} terminated") if verbose: print(f"KILLING ALL APPS because {proc} terminated")
...@@ -488,12 +494,9 @@ def vncsession(vm: str, display_id: int =0, user: str = "u"): ...@@ -488,12 +494,9 @@ def vncsession(vm: str, display_id: int =0, user: str = "u"):
import psutil import psutil
unit_id = random.randint(100000, 999999) unit_id = random.randint(100000, 999999)
vm, user = extended_name(vm, user=user) vm, user = extended_name(vm, user=user)
vm = name_to_id(vm)
vnc_server = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncsession-{display_id}-{unit_id} --user -P bash -c '(cat /vnc_passwd;echo; cat /vnc_passwd; echo;echo n) | vncpasswd; vncserver :{display_id}'", user=user)) vnc_server = subprocess.Popen(ssh_args(vm, f"systemd-run --unit vncsession-{display_id}-{unit_id} --user -P bash -c '(cat /vnc_passwd;echo; cat /vnc_passwd; echo;echo n) | vncpasswd; vncserver :{display_id}'", user=user))
vnc_client_env = os.environ.copy()
vnc_client_env["VNC_PASSWORD"] = open(vm_dir(vm)+"vnc_passwd", "r").read().strip()
time.sleep(1) time.sleep(1)
vnc_client = subprocess.Popen(["vncviewer", get_ip(vm)+f":{display_id}"], env=vnc_client_env) vnc_client = subprocess.Popen(["vncviewer", get_ip(vm)+f":{display_id}", *vncviewer_args], env=get_vnc_client_env(vm))
def on_terminate(proc): def on_terminate(proc):
if verbose: print("KILLING ALL APPS") if verbose: print("KILLING ALL APPS")
...@@ -690,7 +693,7 @@ def modify_net(ucred, vm: str, wan: bool = False, lan: bool = False, pc: bool = ...@@ -690,7 +693,7 @@ def modify_net(ucred, vm: str, wan: bool = False, lan: bool = False, pc: bool =
def start(ucred, vm: str): def start(ucred, vm: str):
vm = name_to_id(vm) vm = name_to_id(vm)
assert has_write_acces(ucred, vm) assert has_write_acces(ucred, vm)
if open(vm_dir(vm)+"network/boot_id", "r").read().strip() != boot_id: if not os.path.exists(vm_dir(vm)+"network/boot_id") or open(vm_dir(vm)+"network/boot_id", "r").read().strip() != boot_id:
create_net(ucred, vm) create_net(ucred, vm)
r("VBoxManage", "startvm", vm, "--type=headless") r("VBoxManage", "startvm", vm, "--type=headless")
if get_permanency(vm).startswith("init "): if get_permanency(vm).startswith("init "):
...@@ -899,6 +902,62 @@ def run(vm: str, prog: str, *arg: tuple[str, ...], gui: bool = False, out_file: ...@@ -899,6 +902,62 @@ def run(vm: str, prog: str, *arg: tuple[str, ...], gui: bool = False, out_file:
########################################################## ##########################################################
def run_args(args):
if verbose: print(args)
if not args.subcommand:
parser.print_help()
else:
import inspect
f = subcommands[args.subcommand]
spec = get_spec(f)
f_kvarg = {}
f_arg = []
def process_arg(name, has_default, default):
if has_default:
if args.__dict__[name] is not None:
f_kvarg[name] = args.__dict__[name]
else:
f_arg.append(args.__dict__[name])
for i, arg in enumerate(spec.args):
has_default = spec.defaults is not None and i >= len(spec.args) - len(spec.defaults)
default = None
if has_default:
default = spec.defaults[i - len(spec.args) + len(spec.defaults)]
process_arg(arg, has_default, default)
for i, arg in enumerate(spec.kwonlyargs):
default = spec.kwonlydefaults[arg]
process_arg(arg, True, default)
if spec.varargs is not None:
arg = spec.varargs
annotation = spec.annotations.get(arg, None)
if annotation == tuple[str, ...]:
f_arg += args.__dict__[arg]
if verbose: print(f_arg, f_kvarg)
r = f(*f_arg, **f_kvarg)
if r is not None:
if isinstance(r, tuple) or isinstance(r, list):
for i in r:
print(i)
else:
print(r)
@cmd
def run_periodically(delay: int, *argv: tuple[str, ...]):
print("RUN PERIODICALLY", argv)
args = parser.parse_args(argv)
while True:
time.sleep(delay)
try:
run_args(args)
except Exception as e:
traceback.print_exception(e)
def main_daemon(): def main_daemon():
import socket import socket
import struct import struct
...@@ -911,7 +970,9 @@ def main_daemon(): ...@@ -911,7 +970,9 @@ def main_daemon():
server.bind(socket_path) server.bind(socket_path)
os.chmod(socket_path, 0o777) os.chmod(socket_path, 0o777)
import traceback
for arg in sys.argv[2:]:
p = subprocess.Popen([sys.argv[0], *arg.split(" ")])
try: try:
while True: while True:
...@@ -949,8 +1010,6 @@ def main_daemon(): ...@@ -949,8 +1010,6 @@ def main_daemon():
except Exception as e: except Exception as e:
traceback.print_exception(e) traceback.print_exception(e)
finally: finally:
# close the connection
# remove the socket file
os.unlink(socket_path) os.unlink(socket_path)
exit(1) exit(1)
...@@ -963,48 +1022,7 @@ def main(): ...@@ -963,48 +1022,7 @@ def main():
if args.root_folder is not None: if args.root_folder is not None:
root_folder = args.root_folder+"/" root_folder = args.root_folder+"/"
if verbose: print(args) run_args(args)
if not args.subcommand:
parser.print_help()
else:
import inspect
f = subcommands[args.subcommand]
spec = get_spec(f)
f_kvarg = {}
f_arg = []
def process_arg(name, has_default, default):
if has_default:
if args.__dict__[name] is not None:
f_kvarg[name] = args.__dict__[name]
else:
f_arg.append(args.__dict__[name])
for i, arg in enumerate(spec.args):
has_default = spec.defaults is not None and i >= len(spec.args) - len(spec.defaults)
default = None
if has_default:
default = spec.defaults[i - len(spec.args) + len(spec.defaults)]
process_arg(arg, has_default, default)
for i, arg in enumerate(spec.kwonlyargs):
default = spec.kwonlydefaults[arg]
process_arg(arg, True, default)
if spec.varargs is not None:
arg = spec.varargs
annotation = spec.annotations.get(arg, None)
if annotation == tuple[str, ...]:
f_arg += args.__dict__[arg]
if verbose: print(f_arg, f_kvarg)
r = f(*f_arg, **f_kvarg)
if r is not None:
if isinstance(r, tuple) or isinstance(r, list):
for i in r:
print(i)
else:
print(r)
......
...@@ -6,7 +6,8 @@ After=network.target ...@@ -6,7 +6,8 @@ After=network.target
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin:/home/jiri/bin Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin:/home/jiri/bin
WorkingDirectory=/mnt/virtual WorkingDirectory=/mnt/virtual
ExecStart=/mnt/virtual/prog/vm.py server ExecStart=/mnt/virtual/prog/vm.py server 'run_periodically 10 -- prepare_forks --base base --count 1' 'run_periodically 30 -- clean'
Restart=always Restart=always
RestartSec=10 RestartSec=10
......