final?
This commit is contained in:
parent
35f3197142
commit
f987c72c5f
|
|
@ -26,7 +26,7 @@ _lxcd_completion() {
|
|||
case "${subcommand}" in
|
||||
create)
|
||||
if [[ "$cur" == -* ]]; then
|
||||
COMPREPLY=($(compgen -W "--nested --sshd --git --certs --aptcache --ssh-client" -- "$cur"))
|
||||
COMPREPLY=($(compgen -W "--nested --sshd --git --certs --aptcache --ssh-client -i --image" -- "$cur"))
|
||||
else
|
||||
COMPREPLY=($(compgen -W "ubuntu: ubuntu/24.04 ubuntu/22.04 debian/12 debian/11" -- "$cur"))
|
||||
fi
|
||||
|
|
|
|||
90
lxcd.py
90
lxcd.py
|
|
@ -115,60 +115,23 @@ def handle_list(args):
|
|||
if addrs:
|
||||
ipv4 = addrs[0]
|
||||
|
||||
# Read lxcd feature labels via individual config get
|
||||
def get_config(key):
|
||||
return lxc_subprocess(
|
||||
["config", "get", name, key],
|
||||
capture_output=True, text=True, check=False
|
||||
).stdout.strip()
|
||||
|
||||
active_opts = []
|
||||
|
||||
# Check nesting (works whether running or stopped)
|
||||
nesting_check = lxc_subprocess(
|
||||
["config", "get", name, "security.nesting"],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if nesting_check.stdout.strip() == "true":
|
||||
# Check nesting via security.nesting (native LXD config)
|
||||
if get_config("security.nesting") == "true":
|
||||
active_opts.append("nesting")
|
||||
|
||||
# Check certs (works whether running or stopped)
|
||||
dev_check = lxc_subprocess(
|
||||
["config", "device", "show", name],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if "host-certs" in dev_check.stdout:
|
||||
active_opts.append("certs")
|
||||
|
||||
# Check git (works whether running or stopped)
|
||||
if "gitconfig" in dev_check.stdout:
|
||||
active_opts.append("git")
|
||||
|
||||
# Running-only checks
|
||||
if status.upper() == "RUNNING":
|
||||
ssh_check = lxc_subprocess(
|
||||
["exec", name, "--", "systemctl", "is-active", "ssh.socket"],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if ssh_check.stdout.strip() == "active":
|
||||
active_opts.append("sshd")
|
||||
|
||||
apt_cache_check = lxc_subprocess(
|
||||
["exec", name, "--", "test", "-f", "/etc/apt/apt.conf.d/00lxcd-proxy"],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if apt_cache_check.returncode == 0:
|
||||
active_opts.append("aptcache")
|
||||
|
||||
ssh_client_check = lxc_subprocess(
|
||||
["exec", name, "--", "which", "ssh"],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if ssh_client_check.returncode == 0:
|
||||
active_opts.append("ssh-client")
|
||||
else:
|
||||
# Offline guess: check cloud-init config for apt proxy
|
||||
ci_check = lxc_subprocess(
|
||||
["config", "get", name, "cloud-init.user-data"],
|
||||
capture_output=True, text=True, check=False
|
||||
)
|
||||
if "Acquire::http::Proxy" in ci_check.stdout:
|
||||
active_opts.append("aptcache(?)")
|
||||
if "openssh-client" in ci_check.stdout:
|
||||
active_opts.append("ssh-client(?)")
|
||||
# Check labels for other features
|
||||
for feature in ("certs", "git", "sshd", "aptcache", "ssh-client"):
|
||||
if get_config(f"user.lxcd.{feature}") == "true":
|
||||
active_opts.append(feature)
|
||||
|
||||
opts_str = ", ".join(active_opts) if active_opts else "none"
|
||||
print(f"{name:<25} {status:<12} {ipv4:<25} {opts_str:<25}")
|
||||
|
|
@ -283,6 +246,7 @@ runcmd:
|
|||
f"source={gitconfig_path}",
|
||||
f"path={container_git_path}",
|
||||
"shift=true"])
|
||||
set_label(args.name, "git")
|
||||
else:
|
||||
print(f"Warning: --git requested, but {gitconfig_path} was not found on host.", file=sys.stderr)
|
||||
|
||||
|
|
@ -291,14 +255,21 @@ runcmd:
|
|||
print("Enabling nesting capabilities...")
|
||||
lxc_run([ "config", "set", args.name, "security.nesting", "true"])
|
||||
lxc_run([ "config", "set", args.name, "security.syscalls.intercept.mknod", "true"])
|
||||
set_label(args.name, "nested")
|
||||
|
||||
# Handle --sshd label (already handled in cloud-init config above)
|
||||
if args.sshd:
|
||||
set_label(args.name, "sshd")
|
||||
|
||||
# Handle --aptcache option
|
||||
if args.aptcache:
|
||||
print(f"APT cache/proxy will be configured to {args.aptcache} via cloud-init...")
|
||||
set_label(args.name, "aptcache")
|
||||
|
||||
# Handle --ssh-client option
|
||||
if args.ssh_client:
|
||||
print(f"SSH client and ~/.ssh directory will be set up for '{host_username}' via cloud-init...")
|
||||
set_label(args.name, "ssh-client")
|
||||
|
||||
# Handle --certs option
|
||||
if args.certs:
|
||||
|
|
@ -309,6 +280,7 @@ runcmd:
|
|||
f"source={host_certs}",
|
||||
f"path={host_certs}",
|
||||
"shift=true"])
|
||||
set_label(args.name, "certs")
|
||||
else:
|
||||
print("Warning: Host cert bundle path not found. Skipping certificate mount configuration.")
|
||||
|
||||
|
|
@ -356,17 +328,17 @@ def handle_enter(args):
|
|||
if display:
|
||||
env_prefix += f"DISPLAY={display} "
|
||||
|
||||
# Check if container has ~/.ssh (set up by --ssh-client) and start ssh-agent if so
|
||||
# Check if container has the ssh-client feature (set by --ssh-client)
|
||||
has_ssh_client = lxc_subprocess(
|
||||
["exec", args.name, "--", "test", "-d", f"{container_home}/.ssh"],
|
||||
["config", "get", args.name, "user.lxcd.ssh-client"],
|
||||
capture_output=True, text=True, check=False
|
||||
).returncode == 0
|
||||
).stdout.strip() == "true"
|
||||
|
||||
# Execute using native LXD flags for user, group, and working directory
|
||||
prefix = lxc_prefix()
|
||||
shell_cmd = "exec /bin/bash --login"
|
||||
if has_ssh_client:
|
||||
shell_cmd = "eval $(ssh-agent) && ssh-add && " + shell_cmd
|
||||
shell_cmd = "eval $(ssh-agent) && ssh-add; " + shell_cmd
|
||||
exec_cmd = [
|
||||
"lxc", "exec", args.name,
|
||||
"--cwd", target_cwd,
|
||||
|
|
@ -405,6 +377,10 @@ def handle_delete(args):
|
|||
lxc_run([ "delete", args.name])
|
||||
print(f"Container '{args.name}' deleted successfully.")
|
||||
|
||||
def set_label(name, feature, value="true"):
|
||||
"""Set a user.lxcd.<feature> config key on a container."""
|
||||
lxc_run([ "config", "set", name, f"user.lxcd.{feature}", value], check=False)
|
||||
|
||||
def container_exists(name):
|
||||
result = lxc_subprocess(
|
||||
["info", name],
|
||||
|
|
@ -439,10 +415,12 @@ def handle_add(args):
|
|||
print(f"Enabling nesting support for '{args.name}'...")
|
||||
lxc_run([ "config", "set", args.name, "security.nesting", "true"])
|
||||
lxc_run([ "config", "set", args.name, "security.syscalls.intercept.mknod", "true"])
|
||||
set_label(args.name, "nested")
|
||||
|
||||
if args.sshd:
|
||||
print(f"Activating SSH daemon and socket inside '{args.name}'...")
|
||||
lxc_run([ "exec", args.name, "--", "systemctl", "enable", "--now", "ssh.service", "ssh.socket"])
|
||||
set_label(args.name, "sshd")
|
||||
|
||||
if args.git:
|
||||
was_running = not was_stopped
|
||||
|
|
@ -460,6 +438,7 @@ def handle_add(args):
|
|||
f"source={host_gitconfig}",
|
||||
f"path=/home/{host_username}/.gitconfig",
|
||||
"shift=true"])
|
||||
set_label(args.name, "git")
|
||||
if was_running:
|
||||
lxc_run([ "start", args.name])
|
||||
lxc_run([ "exec", args.name, "--", "cloud-init", "status", "--wait"], check=False)
|
||||
|
|
@ -476,6 +455,7 @@ def handle_add(args):
|
|||
f"source={host_certs}",
|
||||
f"path={host_certs}",
|
||||
"shift=true"])
|
||||
set_label(args.name, "certs")
|
||||
else:
|
||||
print("Warning: Host cert bundle path not found. Skipping certificate configuration.")
|
||||
|
||||
|
|
@ -484,6 +464,7 @@ def handle_add(args):
|
|||
lxc_run([ "exec", args.name, "--", "mkdir", "-p", "/etc/apt/apt.conf.d"])
|
||||
lxc_run([ "exec", args.name, "--", "sh", "-c",
|
||||
f"echo 'Acquire::http::Proxy \"{args.aptcache}\";' > /etc/apt/apt.conf.d/00lxcd-proxy"])
|
||||
set_label(args.name, "aptcache")
|
||||
|
||||
if args.ssh_client:
|
||||
print(f"Installing SSH client and setting up ~/.ssh inside '{args.name}'...")
|
||||
|
|
@ -492,6 +473,7 @@ def handle_add(args):
|
|||
lxc_run([ "exec", args.name, "--", "mkdir", "-p", f"/home/{host_username}/.ssh"])
|
||||
lxc_run([ "exec", args.name, "--", "chmod", "700", f"/home/{host_username}/.ssh"])
|
||||
lxc_run([ "exec", args.name, "--", "chown", f"{host_username}:{host_username}", f"/home/{host_username}/.ssh"])
|
||||
set_label(args.name, "ssh-client")
|
||||
|
||||
if was_stopped:
|
||||
print(f"Returning '{args.name}' to its original stopped state...")
|
||||
|
|
|
|||
Loading…
Reference in New Issue