From eff2592ae529eaeb241106b086268441b88f2680 Mon Sep 17 00:00:00 2001 From: Basti Qdoba Date: Mon, 27 Feb 2023 20:25:15 +0100 Subject: [PATCH 1/7] Update jlmkr.py --- jlmkr.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/jlmkr.py b/jlmkr.py index aead53e..06bf24c 100644 --- a/jlmkr.py +++ b/jlmkr.py @@ -613,6 +613,20 @@ def create_jail(jail_name): start_jail(jail_name) +def delete_jail(jail_name): + """ + Delete jail with given name. + """ + # stop the jail + os.system(f"machinectl stop {jail_name}") + + jail_path = os.path.join(JAILS_DIR_PATH, jail_name) + + if os.path.isdir(jail_path): + eprint(f"Cleaning up: {jail_path}") + shutil.rmtree(jail_path) + + def main(): if os.stat(__file__).st_uid != 0: fail("This script should be owned by the root user...") @@ -629,6 +643,9 @@ def main(): start_parser = subparsers.add_parser(name='start', epilog=DISCLAIMER) start_parser.add_argument('name', help='name of the jail') + start_parser = subparsers.add_parser(name='delete', epilog=DISCLAIMER) + start_parser.add_argument('name', help='name of the jail') + parser.usage = f"{parser.format_usage()[7:]}{create_parser.format_usage()}{start_parser.format_usage()}" if os.getuid() != 0: @@ -650,6 +667,9 @@ def main(): elif args.subcommand == 'create': create_jail(args.name) + elif args.subcommand == 'delete': + delete_jail(args.name) + elif args.subcommand: parser.print_usage() From 554a3ed0546ce5cbc45c18dd013c0417e5bc5b0f Mon Sep 17 00:00:00 2001 From: Eike Date: Mon, 27 Feb 2023 20:49:25 +0100 Subject: [PATCH 2/7] initial commit --- jlmkr.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jlmkr.py b/jlmkr.py index 06bf24c..d49ceef 100644 --- a/jlmkr.py +++ b/jlmkr.py @@ -185,7 +185,7 @@ def start_jail(jail_name): print(dedent(f""" Starting jail with the following command: - + {shlex.join(cmd)} Starting jail with name: {jail_name} @@ -409,7 +409,7 @@ def create_jail(jail_name): print(dedent(f""" {YELLOW}{BOLD}WARNING: CHECK SYNTAX{NORMAL} - + You may pass additional flags to systemd-nspawn. With incorrect flags the jail may not start. It is possible to correct/add/remove flags post-install. @@ -497,7 +497,7 @@ def create_jail(jail_name): os.path.join(jail_rootfs_path, 'sbin/init'))) != "systemd": print(dedent(f""" {YELLOW}{BOLD}WARNING: DISTRO NOT SUPPORTED{NORMAL} - + Chosen distro appears not to use systemd... You probably will not get a shell with: @@ -628,6 +628,7 @@ def delete_jail(jail_name): def main(): + eprint("hello basti") if os.stat(__file__).st_uid != 0: fail("This script should be owned by the root user...") From dbb1c5f719cc3bbfabbcb4deb70e5cdeabfa7f26 Mon Sep 17 00:00:00 2001 From: Eike Date: Mon, 27 Feb 2023 22:01:36 +0100 Subject: [PATCH 3/7] delete feature added --- jlmkr.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) mode change 100644 => 100755 jlmkr.py diff --git a/jlmkr.py b/jlmkr.py old mode 100644 new mode 100755 index d49ceef..0240e12 --- a/jlmkr.py +++ b/jlmkr.py @@ -617,18 +617,21 @@ def delete_jail(jail_name): """ Delete jail with given name. """ - # stop the jail - os.system(f"machinectl stop {jail_name}") - jail_path = os.path.join(JAILS_DIR_PATH, jail_name) - if os.path.isdir(jail_path): - eprint(f"Cleaning up: {jail_path}") - shutil.rmtree(jail_path) + check = input(f"CAUTION: Type \"{jail_name}\" to confirm! \n") or "" + if check == jail_name: + if os.path.isdir(jail_path): + os.system(f"machinectl stop {jail_name}") + eprint(f"Cleaning up: {jail_path}") + shutil.rmtree(jail_path) + else: + eprint(f"A jail with name {jail_name} does not exist.") + else: + eprint("Wrong name, nothing happens.") def main(): - eprint("hello basti") if os.stat(__file__).st_uid != 0: fail("This script should be owned by the root user...") From 5e0726f9f15e4aee89160d92816d63a4ee3c3e9a Mon Sep 17 00:00:00 2001 From: Eike Date: Tue, 28 Feb 2023 12:17:35 +0100 Subject: [PATCH 4/7] listing available and running containers --- jlmkr.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jlmkr.py b/jlmkr.py index 0240e12..98c137b 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -630,6 +630,16 @@ def delete_jail(jail_name): else: eprint("Wrong name, nothing happens.") +def list_jails(): + """ + List all running jails. + """ + jail_path = os.path.join(JAILS_DIR_PATH) + + eprint("\nAvailable containers:\n") + os.system(f"ls -l {jail_path} | grep '^d' | awk '{{print $NF}}'") + eprint("\nCurrently running containers:\n") + os.system(f"machinectl list") def main(): if os.stat(__file__).st_uid != 0: @@ -650,6 +660,8 @@ def main(): start_parser = subparsers.add_parser(name='delete', epilog=DISCLAIMER) start_parser.add_argument('name', help='name of the jail') + start_parser = subparsers.add_parser(name='list', epilog=DISCLAIMER) + parser.usage = f"{parser.format_usage()[7:]}{create_parser.format_usage()}{start_parser.format_usage()}" if os.getuid() != 0: @@ -674,6 +686,9 @@ def main(): elif args.subcommand == 'delete': delete_jail(args.name) + elif args.subcommand == 'list': + list_jails() + elif args.subcommand: parser.print_usage() From 218aa02cd0498b6f1520b5ee22f00a9710564544 Mon Sep 17 00:00:00 2001 From: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:25:11 +0100 Subject: [PATCH 5/7] Update jlmkr.py --- jlmkr.py | 94 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/jlmkr.py b/jlmkr.py index f850760..a1795b5 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -13,6 +13,7 @@ import shutil import stat import subprocess import sys +import time import urllib.request from inspect import cleandoc @@ -59,12 +60,16 @@ def fail(*args, **kwargs): sys.exit(1) +def get_jail_path(jail_name): + return os.path.join(JAILS_DIR_PATH, jail_name) + + def start_jail(jail_name): """ Start jail with given name. """ - jail_path = os.path.join(JAILS_DIR_PATH, jail_name) + jail_path = get_jail_path(jail_name) jail_config_path = os.path.join(jail_path, JAIL_CONFIG_NAME) config = configparser.ConfigParser() @@ -281,6 +286,38 @@ def get_mount_point(path): return path +def check_jail_name_valid(jail_name, warn=True): + """ + Return True if jail name matches the required format. + """ + if re.match(r"^[.a-zA-Z0-9-]{1,64}$", jail_name) and not jail_name.startswith(".") and ".." not in jail_name: + return True + + if warn: + eprint(dedent(f""" + {YELLOW}{BOLD}WARNING: INVALID NAME{NORMAL} + + A valid name consists of: + - allowed characters (alphanumeric, dash, dot) + - no leading or trailing dots + - no sequences of multiple dots + - max 64 characters""")) + return False + + +def check_jail_name_available(jail_name, warn=True): + """ + Return True if jail name is not yet taken. + """ + if not os.path.exists(get_jail_path(jail_name)): + return True + + if warn: + print() + eprint("A jail with this name already exists.") + return False + + def create_jail(jail_name): """ Create jail with given name. @@ -362,29 +399,14 @@ def create_jail(jail_name): release = input("Release: ") - jail_path = None - - while jail_path == None: + while True: print() jail_name = input_with_default("Enter jail name: ", jail_name).strip() - if not re.match(r"^[.a-zA-Z0-9-]{1,64}$", jail_name) or jail_name.startswith(".") or ".." in jail_name: - eprint(dedent(f""" + if check_jail_name_valid(jail_name): + if check_jail_name_available(jail_name): + break - {YELLOW}{BOLD}WARNING: INVALID NAME{NORMAL} - - A valid name consists of: - - allowed characters (alphanumeric, dash, dot) - - no leading or trailing dots - - no sequences of multiple dots - - max 64 characters - - """)) - else: - jail_path = os.path.join(JAILS_DIR_PATH, jail_name) - if os.path.exists(jail_path): - print() - eprint("A jail with this name already exists.") - jail_path = None + jail_path = get_jail_path(jail_name) # Cleanup in except, but only once the jail_path is final # Otherwise we may cleanup the wrong directory @@ -617,18 +639,21 @@ def delete_jail(jail_name): """ Delete jail with given name. """ - jail_path = os.path.join(JAILS_DIR_PATH, jail_name) - check = input(f"CAUTION: Type \"{jail_name}\" to confirm! \n") or "" - if check == jail_name: - if os.path.isdir(jail_path): - os.system(f"machinectl stop {jail_name}") - eprint(f"Cleaning up: {jail_path}") - shutil.rmtree(jail_path) - else: + if check_jail_name_valid(jail_name): + if check_jail_name_available(jail_name, False): eprint(f"A jail with name {jail_name} does not exist.") - else: - eprint("Wrong name, nothing happens.") + else: + check = input(f'CAUTION: Type "{jail_name}" to confirm jail deletion! \n') or "" + if check == jail_name: + jail_path = get_jail_path(jail_name) + print(f"Trying to stop {jail_path} if it was running...") + subprocess.run(['machinectl', 'stop', jail_name]) + time.sleep(1) + print(f"Cleaning up: {jail_path}") + shutil.rmtree(jail_path) + else: + eprint("Wrong name, nothing happened.") def main(): @@ -642,13 +667,14 @@ def main(): subparsers = parser.add_subparsers(title='commands', dest='subcommand') create_parser = subparsers.add_parser(name='create', epilog=DISCLAIMER) - create_parser.add_argument('name', nargs='?', help='name of the jail') + create_parser.add_argument( + 'name', nargs='?', help='name of the jail to create') start_parser = subparsers.add_parser(name='start', epilog=DISCLAIMER) - start_parser.add_argument('name', help='name of the jail') + start_parser.add_argument('name', help='name of the jail to start') start_parser = subparsers.add_parser(name='delete', epilog=DISCLAIMER) - start_parser.add_argument('name', help='name of the jail') + start_parser.add_argument('name', help='name of the jail to delete') parser.usage = f"{parser.format_usage()[7:]}{create_parser.format_usage()}{start_parser.format_usage()}" From 5193085ad34b2dfe7c102a41d96e950d55814a11 Mon Sep 17 00:00:00 2001 From: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:49:44 +0100 Subject: [PATCH 6/7] Don't use ls grep and awk in python --- jlmkr.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/jlmkr.py b/jlmkr.py index c187575..c277be8 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -647,11 +647,12 @@ def delete_jail(jail_name): if check_jail_name_available(jail_name, False): eprint(f"A jail with name {jail_name} does not exist.") else: - check = input(f'CAUTION: Type "{jail_name}" to confirm jail deletion! \n') or "" + check = input(f'\nCAUTION: Type "{jail_name}" to confirm jail deletion!\n\n') or "" if check == jail_name: jail_path = get_jail_path(jail_name) - print(f"Trying to stop {jail_path} if it was running...") + print(f"\nTrying to stop {jail_name} if it was running...") subprocess.run(['machinectl', 'stop', jail_name]) + # Need to sleep since deleting immediately after stop causes problems... time.sleep(1) print(f"Cleaning up: {jail_path}") shutil.rmtree(jail_path) @@ -660,13 +661,19 @@ def delete_jail(jail_name): def list_jails(): """ - List all running jails. + List all available and running jails. """ - jail_path = os.path.join(JAILS_DIR_PATH) - eprint("\nAvailable containers:\n") - os.system(f"ls -l {jail_path} | grep '^d' | awk '{{print $NF}}'") - eprint("\nCurrently running containers:\n") + jails = os.listdir(JAILS_DIR_PATH) + + print("Available jails:\n") + if not len(jails): + print("No jails.") + else: + for jail in jails: + print(f"{jail}") + + print("\nCurrently running:\n") os.system(f"machinectl list") def main(): From 2de050c0b170533256156cda42b7a44158efba8e Mon Sep 17 00:00:00 2001 From: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:54:50 +0100 Subject: [PATCH 7/7] Only list subdirectories (not files) --- jlmkr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jlmkr.py b/jlmkr.py index c277be8..3d842a9 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -664,7 +664,7 @@ def list_jails(): List all available and running jails. """ - jails = os.listdir(JAILS_DIR_PATH) + jails = next(os.walk('jails'))[1] print("Available jails:\n") if not len(jails):