mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-10-08 14:36:38 +00:00
fix(i18n): natural Spanish for the menus and the OCI catalogue.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"""The menus that install drivers inside a container leave out the ones
|
||||
created from an OCI image: those are changed from OCI manager Apps."""
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
from unittest import TestCase
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
MENUS = ('scripts/gpu_tpu/add_gpu_lxc.sh', 'scripts/gpu_tpu/install_coral_lxc.sh')
|
||||
ORDINARY = "arch: amd64\ncores: 2\nhostname: debian\nostype: debian\nrootfs: local-lvm:vm-111-disk-0,size=8G\n"
|
||||
OCI = ORDINARY + "entrypoint: /init\nlxc.signal.halt: SIGTERM\n"
|
||||
|
||||
|
||||
def function(path, name):
|
||||
source = (ROOT / path).read_text()
|
||||
return re.search(rf'^{name}\(\) \{{\n.*?^\}}\n', source, re.MULTILINE | re.DOTALL)[0]
|
||||
|
||||
|
||||
class GpuMenusHideOci(TestCase):
|
||||
def is_oci(self, config):
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
(Path(folder) / '111.conf').write_text(config)
|
||||
helper = function('scripts/utils.sh', 'pmx_lxc_is_oci').replace('/etc/pve/lxc', folder)
|
||||
return subprocess.run(['bash', '-c', helper + 'pmx_lxc_is_oci 111'], capture_output=True).returncode == 0
|
||||
|
||||
def test_a_container_from_an_oci_image_is_told_apart_by_its_configuration(self):
|
||||
self.assertTrue(self.is_oci(OCI))
|
||||
self.assertTrue(self.is_oci(ORDINARY + "cmd: nginx -g 'daemon off;'\n"))
|
||||
self.assertFalse(self.is_oci(ORDINARY))
|
||||
# A setting that only mentions the word is not an entrypoint.
|
||||
self.assertFalse(self.is_oci(ORDINARY + "description: entrypoint: none\n"))
|
||||
|
||||
def test_a_container_without_configuration_is_not_one(self):
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
helper = function('scripts/utils.sh', 'pmx_lxc_is_oci').replace('/etc/pve/lxc', folder)
|
||||
self.assertNotEqual(subprocess.run(['bash', '-c', helper + 'pmx_lxc_is_oci 999'],
|
||||
capture_output=True).returncode, 0)
|
||||
|
||||
def test_both_menus_skip_them_and_say_so(self):
|
||||
for menu in MENUS:
|
||||
body = function(menu, 'select_container')
|
||||
self.assertLess(body.index('pmx_lxc_is_oci "$ctid"'), body.index('menu_items+=('), menu)
|
||||
self.assertIn('Containers created from an OCI image are not listed:', body, menu)
|
||||
self.assertEqual(body.count('${oci_note}'), 2, menu)
|
||||
|
||||
|
||||
SWITCHES = (('scripts/gpu_tpu/switch_gpu_mode.sh', 'apply_lxc_action_for_vm_mode', 'prompt_lxc_action_for_vm_mode'),
|
||||
('scripts/gpu_tpu/switch_gpu_mode_direct.sh', 'apply_lxc_action_for_vm_mode', 'prompt_lxc_action_for_vm_mode'),
|
||||
('scripts/gpu_tpu/add_gpu_vm.sh', 'cleanup_lxc_configs', None))
|
||||
|
||||
|
||||
class GpuToVmKeepsOciConfiguration(TestCase):
|
||||
"""A GPU that moves to a VM stops the containers that use it. One created
|
||||
from an OCI image keeps its configuration, which OCI manager Apps records."""
|
||||
|
||||
def test_an_oci_container_is_never_edited(self):
|
||||
for script, apply, _ in SWITCHES:
|
||||
body = function(script, apply)
|
||||
guard = body.index('pmx_lxc_is_oci "$ctid"')
|
||||
self.assertLess(guard, body.index('action="keep_gpu_disable_onboot"'), script)
|
||||
removal = body.index('"$action" == "remove_gpu_keep_onboot"')
|
||||
self.assertLess(guard, removal, script)
|
||||
# The only edit of a configuration hangs from the per-container action.
|
||||
self.assertEqual(len(re.findall(r'_from_lxc_conf "\$', body)), 1, script)
|
||||
edit = body.index('_from_lxc_conf "$')
|
||||
condition = body.rindex('if [[', 0, edit)
|
||||
self.assertIn('"$action" == "remove_gpu_keep_onboot"', body[condition:edit], script)
|
||||
|
||||
def test_the_list_names_them_and_nothing_is_asked_when_all_are_oci(self):
|
||||
for script, _, prompt in SWITCHES:
|
||||
source = (ROOT / script).read_text() if prompt is None else function(script, prompt)
|
||||
self.assertIn('", OCI"', source, script)
|
||||
self.assertIn('OCI containers keep their configuration', source, script)
|
||||
self.assertIn('"$oci_count" -eq ${#LXC_AFFECTED_CTIDS[@]}', source, script)
|
||||
|
||||
|
||||
class DiskAndSharePickersHideOci(TestCase):
|
||||
"""Adding a disk or a mount, and the NFS and Samba set-ups, change the
|
||||
container they are given. A container from an OCI image is not offered."""
|
||||
|
||||
def test_every_picker_filters_before_it_lists(self):
|
||||
pickers = ((function('scripts/global/share-common.func', 'select_lxc_container'), 'options+=('),
|
||||
(function('scripts/global/share-common.func', 'select_privileged_lxc'), 'ct_list+='),
|
||||
(function('scripts/share/lxc-mount-manager_minimal.sh', 'select_lxc_container'), 'options+=('))
|
||||
for body, listing in pickers:
|
||||
self.assertLess(body.index('pmx_lxc_is_oci "$id"'), body.index(listing))
|
||||
self.assertIn('Containers created from an OCI image are not listed', body)
|
||||
disk = (ROOT / 'scripts/storage/disk-passthrough_ct.sh').read_text()
|
||||
picker = disk[disk.index('CT_LIST=""'):disk.index('if [ -z "$CTID" ]')]
|
||||
self.assertLess(picker.index('pmx_lxc_is_oci "$ct_id"'), picker.index('CT_LIST+='))
|
||||
self.assertIn('${OCI_NOTE}" $UI_MENU_H $UI_MENU_W $CT_LIST_H', picker)
|
||||
|
||||
def test_a_disk_in_use_is_still_looked_for_in_every_container(self):
|
||||
for script in ('scripts/storage/disk-passthrough_ct.sh', 'scripts/storage/disk-passthrough.sh'):
|
||||
source = (ROOT / script).read_text()
|
||||
check = source[source.index('disk_referenced_in_config "$CT_CONFIG_RAW" "$DISK"'):]
|
||||
scan = check[:check.index("done < <(pct list | awk 'NR>1 {print $1, $3}')")]
|
||||
self.assertNotIn('pmx_lxc_is_oci', scan, script)
|
||||
+1531
-1526
File diff suppressed because it is too large
Load Diff
@@ -449,15 +449,26 @@ select_lxc_container() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
local options=()
|
||||
local options=() oci_note="" list_h=15
|
||||
while read -r id name status; do
|
||||
if [[ -n "$id" ]]; then
|
||||
if pmx_lxc_is_oci "$id"; then
|
||||
list_h=12
|
||||
oci_note="\n\n$(translate "Containers created from an OCI image are not listed: their paths are changed in OCI manager Apps (Recreate).")"
|
||||
continue
|
||||
fi
|
||||
options+=("$id" "$name ($status)")
|
||||
fi
|
||||
done <<< "$ct_list"
|
||||
|
||||
if [[ ${#options[@]} -eq 0 ]]; then
|
||||
dialog --title "$(translate "Error")" \
|
||||
--msgbox "$(translate "No LXC containers available")${oci_note}" 12 66
|
||||
return 1
|
||||
fi
|
||||
|
||||
ctid=$(dialog --title "$(translate "Select LXC Container")" \
|
||||
--menu "\n$(translate "Select container:")" 25 80 15 \
|
||||
--menu "\n$(translate "Select container:")${oci_note}" 25 80 "$list_h" \
|
||||
"${options[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ -z "$ctid" ]]; then
|
||||
@@ -600,15 +611,24 @@ select_privileged_lxc() {
|
||||
# === Select CT ===
|
||||
local ct_list ctid ct_status conf unpriv
|
||||
|
||||
ct_list=$(pct list | awk 'NR>1 {print $1, $3}')
|
||||
local oci_note="" list_h=12 id name
|
||||
while read -r id name; do
|
||||
[[ -n "$id" ]] || continue
|
||||
if pmx_lxc_is_oci "$id"; then
|
||||
list_h=8
|
||||
oci_note="\n\n$(translate "Containers created from an OCI image are not listed.")"
|
||||
continue
|
||||
fi
|
||||
ct_list+="${ct_list:+ }$id ${name:-CT-$id}"
|
||||
done < <(pct list | awk 'NR>1 {print $1, $3}')
|
||||
if [[ -z "$ct_list" ]]; then
|
||||
dialog --backtitle "ProxMenux" --title "$(translate "Error")" \
|
||||
--msgbox "$(translate "No CTs available in the system.")" 8 50
|
||||
--msgbox "$(translate "No CTs available in the system.")${oci_note}" 10 60
|
||||
return 1
|
||||
fi
|
||||
|
||||
ctid=$(dialog --backtitle "ProxMenux" --title "$(translate "Select CT")" \
|
||||
--menu "$(translate "Select the CT to manage NFS/Samba client:")" 20 70 12 \
|
||||
--menu "$(translate "Select the CT to manage NFS/Samba client:")${oci_note}" 20 70 "$list_h" \
|
||||
$ct_list 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ -z "$ctid" ]]; then
|
||||
|
||||
@@ -251,7 +251,7 @@ detect_host_gpus() {
|
||||
# Container selection
|
||||
# ============================================================
|
||||
select_container() {
|
||||
local menu_items=()
|
||||
local menu_items=() oci_hidden=0
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" =~ ^VMID ]] && continue
|
||||
local ctid status name
|
||||
@@ -259,19 +259,26 @@ select_container() {
|
||||
status=$(echo "$line" | awk '{print $2}')
|
||||
name=$(echo "$line" | awk '{print $3}')
|
||||
[[ -z "$ctid" ]] && continue
|
||||
if pmx_lxc_is_oci "$ctid"; then
|
||||
oci_hidden=$((oci_hidden + 1))
|
||||
continue
|
||||
fi
|
||||
menu_items+=("$ctid" "${name:-CT-${ctid}} (${status})")
|
||||
done < <(pct list 2>/dev/null)
|
||||
|
||||
local oci_note="" list_h=12
|
||||
[[ $oci_hidden -gt 0 ]] && list_h=7 && oci_note="\n\n$(translate 'Containers created from an OCI image are not listed: their devices are changed in OCI manager Apps (Recreate).')"
|
||||
|
||||
if [[ ${#menu_items[@]} -eq 0 ]]; then
|
||||
dialog --backtitle "ProxMenux" \
|
||||
--title "$(translate 'Add GPU to LXC')" \
|
||||
--msgbox "\n$(translate 'No LXC containers found on this system.')" 8 60
|
||||
--msgbox "\n$(translate 'No LXC containers found on this system.')${oci_note}" 12 66
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CONTAINER_ID=$(dialog --backtitle "ProxMenux" \
|
||||
--title "$(translate 'Add GPU to LXC')" \
|
||||
--menu "\n$(translate 'Select the LXC container:')" 20 72 12 \
|
||||
--menu "\n$(translate 'Select the LXC container:')${oci_note}" 20 72 "$list_h" \
|
||||
"${menu_items[@]}" \
|
||||
2>&1 >/dev/tty) || exit 0
|
||||
}
|
||||
|
||||
@@ -1402,7 +1402,7 @@ check_switch_mode() {
|
||||
SWITCH_FROM_LXC=true
|
||||
SWITCH_LXC_LIST=$(IFS=', '; echo "${lxc_affected[*]}")
|
||||
|
||||
local msg action_choice
|
||||
local msg action_choice oci_count=0
|
||||
msg="\n$(translate 'The selected GPU is currently used by the following LXC container(s):')\n\n"
|
||||
local i
|
||||
for i in "${!LXC_AFFECTED_CTIDS[@]}"; do
|
||||
@@ -1411,8 +1411,13 @@ check_switch_mode() {
|
||||
onboot_txt="onboot=0"
|
||||
[[ "${LXC_AFFECTED_RUNNING[$i]}" == "1" ]] && status_txt="$(translate 'running')"
|
||||
[[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]] && onboot_txt="onboot=1"
|
||||
if pmx_lxc_is_oci "${LXC_AFFECTED_CTIDS[$i]}"; then
|
||||
onboot_txt+=", OCI"
|
||||
oci_count=$((oci_count + 1))
|
||||
fi
|
||||
msg+=" • CT ${LXC_AFFECTED_CTIDS[$i]} (${LXC_AFFECTED_NAMES[$i]}) [${status_txt}, ${onboot_txt}]\n"
|
||||
done
|
||||
[[ "$oci_count" -gt 0 ]] && msg+="\n$(translate 'OCI containers keep their configuration: they are stopped and their Start on boot is disabled. Their GPU is removed from OCI manager Apps, with Recreate.')\n"
|
||||
msg+="\n$(translate 'VM passthrough requires exclusive VFIO binding of the GPU.')\n"
|
||||
msg+="$(translate 'Choose how to handle affected LXC containers before switching to VM mode.')\n\n"
|
||||
[[ "$running_count" -gt 0 ]] && \
|
||||
@@ -1421,17 +1426,22 @@ check_switch_mode() {
|
||||
msg+="\Z1\Zb$(translate 'Start on boot enabled (onboot=1)'): ${onboot_count}\Zn\n"
|
||||
msg+="\n\Z1$(translate 'After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.')\Zn"
|
||||
|
||||
action_choice=$(_pmx_menu --default-item "2" \
|
||||
"$(translate 'GPU Used in LXC Containers')" \
|
||||
"$msg" 25 96 8 \
|
||||
"1" "$(translate 'Keep GPU in LXC config (disable Start on boot)')" \
|
||||
"2" "$(translate 'Remove GPU from LXC config (keep Start on boot)')") || exit 0
|
||||
if [[ "$oci_count" -eq ${#LXC_AFFECTED_CTIDS[@]} ]]; then
|
||||
LXC_SWITCH_ACTION="keep_gpu_disable_onboot"
|
||||
_pmx_msgbox "$(translate 'GPU Used in LXC Containers')" "$msg" 25 96
|
||||
else
|
||||
action_choice=$(_pmx_menu --default-item "2" \
|
||||
"$(translate 'GPU Used in LXC Containers')" \
|
||||
"$msg" 25 96 8 \
|
||||
"1" "$(translate 'Keep GPU in LXC config (disable Start on boot)')" \
|
||||
"2" "$(translate 'Remove GPU from LXC config (keep Start on boot)')") || exit 0
|
||||
|
||||
case "$action_choice" in
|
||||
1) LXC_SWITCH_ACTION="keep_gpu_disable_onboot" ;;
|
||||
2) LXC_SWITCH_ACTION="remove_gpu_keep_onboot" ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
case "$action_choice" in
|
||||
1) LXC_SWITCH_ACTION="keep_gpu_disable_onboot" ;;
|
||||
2) LXC_SWITCH_ACTION="remove_gpu_keep_onboot" ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
SWITCH_FROM_LXC=false
|
||||
fi
|
||||
@@ -1942,7 +1952,15 @@ cleanup_lxc_configs() {
|
||||
msg_ok "$(translate 'LXC already stopped') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
if [[ "$LXC_SWITCH_ACTION" == "keep_gpu_disable_onboot" ]]; then
|
||||
# OCI manager Apps keeps the record of what an OCI container has: its
|
||||
# configuration is not edited from here.
|
||||
local action="$LXC_SWITCH_ACTION"
|
||||
if pmx_lxc_is_oci "$ctid"; then
|
||||
action="keep_gpu_disable_onboot"
|
||||
msg_warn "$(translate 'OCI container, configuration kept. Remove its GPU from OCI manager Apps, with Recreate: CT') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
if [[ "$action" == "keep_gpu_disable_onboot" ]]; then
|
||||
if [[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]]; then
|
||||
if pct set "$ctid" -onboot 0 >>"$LOG_FILE" 2>&1; then
|
||||
msg_warn "$(translate 'Start on boot disabled for LXC') ${ctid}" | tee -a "$screen_capture"
|
||||
@@ -1952,7 +1970,7 @@ cleanup_lxc_configs() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LXC_SWITCH_ACTION" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
if [[ "$action" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
_remove_selected_gpu_from_lxc_conf "$conf"
|
||||
msg_ok "$(translate 'GPU access removed from LXC') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
@@ -63,7 +63,7 @@ initialize_cache
|
||||
# ==========================================================
|
||||
|
||||
select_container() {
|
||||
local menu_items=()
|
||||
local menu_items=() oci_hidden=0
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" =~ ^VMID ]] && continue
|
||||
local ctid status name
|
||||
@@ -71,19 +71,26 @@ select_container() {
|
||||
status=$(echo "$line" | awk '{print $2}')
|
||||
name=$(echo "$line" | awk '{print $3}')
|
||||
[[ -z "$ctid" ]] && continue
|
||||
if pmx_lxc_is_oci "$ctid"; then
|
||||
oci_hidden=$((oci_hidden + 1))
|
||||
continue
|
||||
fi
|
||||
menu_items+=("$ctid" "${name:-CT-${ctid}} (${status})")
|
||||
done < <(pct list 2>/dev/null)
|
||||
|
||||
local oci_note="" list_h=12
|
||||
[[ $oci_hidden -gt 0 ]] && list_h=7 && oci_note="\n\n$(translate 'Containers created from an OCI image are not listed: their devices are changed in OCI manager Apps (Recreate).')"
|
||||
|
||||
if [[ ${#menu_items[@]} -eq 0 ]]; then
|
||||
dialog --backtitle "ProxMenux" \
|
||||
--title "$(translate 'Install Coral TPU in LXC')" \
|
||||
--msgbox "\n$(translate 'No LXC containers found on this system.')" 8 60
|
||||
--msgbox "\n$(translate 'No LXC containers found on this system.')${oci_note}" 12 66
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CONTAINER_ID=$(dialog --backtitle "ProxMenux" \
|
||||
--title "$(translate 'Install Coral TPU in LXC')" \
|
||||
--menu "\n$(translate 'Select the LXC container:')" 20 72 12 \
|
||||
--menu "\n$(translate 'Select the LXC container:')${oci_note}" 20 72 "$list_h" \
|
||||
"${menu_items[@]}" \
|
||||
2>&1 >/dev/tty) || exit 0
|
||||
|
||||
|
||||
@@ -770,7 +770,7 @@ detect_affected_lxc_for_selected() {
|
||||
prompt_lxc_action_for_vm_mode() {
|
||||
[[ ${#LXC_AFFECTED_CTIDS[@]} -eq 0 ]] && return 0
|
||||
|
||||
local running_count=0 onboot_count=0 i
|
||||
local running_count=0 onboot_count=0 oci_count=0 i
|
||||
for i in "${!LXC_AFFECTED_CTIDS[@]}"; do
|
||||
[[ "${LXC_AFFECTED_RUNNING[$i]}" == "1" ]] && running_count=$((running_count + 1))
|
||||
[[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]] && onboot_count=$((onboot_count + 1))
|
||||
@@ -783,11 +783,23 @@ prompt_lxc_action_for_vm_mode() {
|
||||
st="$(translate 'stopped')"; ob="onboot=0"
|
||||
[[ "${LXC_AFFECTED_RUNNING[$i]}" == "1" ]] && st="$(translate 'running')"
|
||||
[[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]] && ob="onboot=1"
|
||||
if pmx_lxc_is_oci "${LXC_AFFECTED_CTIDS[$i]}"; then
|
||||
ob+=", OCI"
|
||||
oci_count=$((oci_count + 1))
|
||||
fi
|
||||
msg+=" • CT ${LXC_AFFECTED_CTIDS[$i]} (${LXC_AFFECTED_NAMES[$i]}) [${st}, ${ob}]\n"
|
||||
done
|
||||
[[ "$oci_count" -gt 0 ]] && msg+="\n$(translate 'OCI containers keep their configuration: they are stopped and their Start on boot is disabled. Their GPU is removed from OCI manager Apps, with Recreate.')\n"
|
||||
msg+="\n$(translate 'Switching to GPU -> VM mode requires exclusive VFIO binding.')\n"
|
||||
[[ "$running_count" -gt 0 ]] && msg+="\Z1$(translate 'Running containers detected'): ${running_count}\Zn\n"
|
||||
[[ "$onboot_count" -gt 0 ]] && msg+="\Z1\Zb$(translate 'Start on boot enabled'): ${onboot_count}\Zn\n"
|
||||
if [[ "$oci_count" -eq ${#LXC_AFFECTED_CTIDS[@]} ]]; then
|
||||
LXC_ACTION="keep_gpu_disable_onboot"
|
||||
dialog --backtitle "ProxMenux" --colors \
|
||||
--title "$(translate 'LXC Conflict Policy')" \
|
||||
--msgbox "$msg" 22 80
|
||||
return 0
|
||||
fi
|
||||
msg+="\n$(translate 'Choose conflict policy:')"
|
||||
|
||||
choice=$(dialog --backtitle "ProxMenux" --colors \
|
||||
@@ -849,13 +861,21 @@ apply_lxc_action_for_vm_mode() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LXC_ACTION" == "keep_gpu_disable_onboot" && "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]]; then
|
||||
# OCI manager Apps keeps the record of what an OCI container has: its
|
||||
# configuration is not edited from here.
|
||||
local action="$LXC_ACTION"
|
||||
if pmx_lxc_is_oci "$ctid"; then
|
||||
action="keep_gpu_disable_onboot"
|
||||
msg_warn "$(translate 'OCI container, configuration kept. Remove its GPU from OCI manager Apps, with Recreate: CT') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
if [[ "$action" == "keep_gpu_disable_onboot" && "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]]; then
|
||||
if pct set "$ctid" -onboot 0 >>"$LOG_FILE" 2>&1; then
|
||||
msg_warn "$(translate 'Start on boot disabled for LXC') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LXC_ACTION" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
if [[ "$action" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
local t
|
||||
for t in "${types[@]}"; do
|
||||
_remove_type_from_lxc_conf "$conf" "$t"
|
||||
|
||||
@@ -596,7 +596,7 @@ detect_affected_lxc_for_selected() {
|
||||
prompt_lxc_action_for_vm_mode() {
|
||||
[[ ${#LXC_AFFECTED_CTIDS[@]} -eq 0 ]] && return 0
|
||||
|
||||
local running_count=0 onboot_count=0 i
|
||||
local running_count=0 onboot_count=0 oci_count=0 i
|
||||
for i in "${!LXC_AFFECTED_CTIDS[@]}"; do
|
||||
[[ "${LXC_AFFECTED_RUNNING[$i]}" == "1" ]] && running_count=$((running_count + 1))
|
||||
[[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]] && onboot_count=$((onboot_count + 1))
|
||||
@@ -609,11 +609,21 @@ prompt_lxc_action_for_vm_mode() {
|
||||
st="$(translate 'stopped')"; ob="onboot=0"
|
||||
[[ "${LXC_AFFECTED_RUNNING[$i]}" == "1" ]] && st="$(translate 'running')"
|
||||
[[ "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]] && ob="onboot=1"
|
||||
if pmx_lxc_is_oci "${LXC_AFFECTED_CTIDS[$i]}"; then
|
||||
ob+=", OCI"
|
||||
oci_count=$((oci_count + 1))
|
||||
fi
|
||||
msg+=" - CT ${LXC_AFFECTED_CTIDS[$i]} (${LXC_AFFECTED_NAMES[$i]}) [${st}, ${ob}]\n"
|
||||
done
|
||||
[[ "$oci_count" -gt 0 ]] && msg+="\n$(translate 'OCI containers keep their configuration: they are stopped and their Start on boot is disabled. Their GPU is removed from OCI manager Apps, with Recreate.')\n"
|
||||
msg+="\n$(translate 'Switching to GPU -> VM mode requires exclusive VFIO binding.')\n"
|
||||
[[ "$running_count" -gt 0 ]] && msg+="$(translate 'Running containers detected'): ${running_count}\n"
|
||||
[[ "$onboot_count" -gt 0 ]] && msg+="$(translate 'Start on boot enabled'): ${onboot_count}\n"
|
||||
if [[ "$oci_count" -eq ${#LXC_AFFECTED_CTIDS[@]} ]]; then
|
||||
LXC_ACTION="keep_gpu_disable_onboot"
|
||||
hybrid_msgbox "$(translate 'LXC Conflict Policy')" "$msg" 22 80
|
||||
return 0
|
||||
fi
|
||||
msg+="\n$(translate 'Choose conflict policy'):"
|
||||
|
||||
local choice
|
||||
@@ -675,13 +685,21 @@ apply_lxc_action_for_vm_mode() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LXC_ACTION" == "keep_gpu_disable_onboot" && "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]]; then
|
||||
# OCI manager Apps keeps the record of what an OCI container has: its
|
||||
# configuration is not edited from here.
|
||||
local action="$LXC_ACTION"
|
||||
if pmx_lxc_is_oci "$ctid"; then
|
||||
action="keep_gpu_disable_onboot"
|
||||
msg_warn "$(translate 'OCI container, configuration kept. Remove its GPU from OCI manager Apps, with Recreate: CT') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
if [[ "$action" == "keep_gpu_disable_onboot" && "${LXC_AFFECTED_ONBOOT[$i]}" == "1" ]]; then
|
||||
if pct set "$ctid" -onboot 0 >>"$LOG_FILE" 2>&1; then
|
||||
msg_warn "$(translate 'Start on boot disabled for LXC') ${ctid}" | tee -a "$screen_capture"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$LXC_ACTION" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
if [[ "$action" == "remove_gpu_keep_onboot" && -f "$conf" ]]; then
|
||||
local t
|
||||
for t in "${types[@]}"; do
|
||||
_remove_type_from_lxc_conf "$conf" "$t"
|
||||
|
||||
@@ -34,14 +34,14 @@ while true; do
|
||||
OPTION=$(dialog --colors --backtitle "ProxMenux" \
|
||||
--title "$(translate "Storage & Share Manager")" \
|
||||
--menu "\n$(translate "Select an option:")" 28 78 17 \
|
||||
"" "\Zb\Z4 HOST\Zn" \
|
||||
"" "\Z4──────────────────────────── HOST ─────────────────────────────\Zn" \
|
||||
"1" "$(translate "Add NFS share as Proxmox Storage")" \
|
||||
"2" "$(translate "Add Samba share as Proxmox Storage")" \
|
||||
"3" "$(translate "Add iSCSI Target as Proxmox Storage")" \
|
||||
"4" "$(translate "Add Local Disk as Proxmox Storage")" \
|
||||
"5" "$(translate "Create Shared Directory on Host")" \
|
||||
"" "" \
|
||||
"" "\Zb\Z4 LXC\Zn" \
|
||||
"" "\Z4───────────────────────────── LXC ─────────────────────────────\Zn" \
|
||||
"6" "$(translate "Configure LXC Mount Points (Host ↔ Container)")" \
|
||||
"" "" \
|
||||
"7" "$(translate "Configure NFS Client in LXC (only privileged)")" \
|
||||
|
||||
@@ -266,19 +266,25 @@ select_lxc_container() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
local options=()
|
||||
local options=() oci_note="" list_h=15
|
||||
while read -r id name status; do
|
||||
[[ -n "$id" && "$id" =~ ^[0-9]+$ ]] && options+=("$id" "${name:-unnamed} ($status)")
|
||||
[[ -n "$id" && "$id" =~ ^[0-9]+$ ]] || continue
|
||||
if pmx_lxc_is_oci "$id"; then
|
||||
list_h=12
|
||||
oci_note="\n\n$(translate "Containers created from an OCI image are not listed: their paths are changed in OCI manager Apps (Recreate).")"
|
||||
continue
|
||||
fi
|
||||
options+=("$id" "${name:-unnamed} ($status)")
|
||||
done <<< "$ct_list"
|
||||
|
||||
if [[ ${#options[@]} -eq 0 ]]; then
|
||||
dialog --title "Error" --msgbox "$(translate "No valid containers found")" 8 50
|
||||
dialog --title "Error" --msgbox "$(translate "No valid containers found")${oci_note}" 12 66
|
||||
return 1
|
||||
fi
|
||||
|
||||
local ctid
|
||||
ctid=$(dialog --title "$(translate "Select LXC Container")" \
|
||||
--menu "$(translate "Select container:")" 25 85 15 \
|
||||
--menu "$(translate "Select container:")${oci_note}" 25 85 "$list_h" \
|
||||
"${options[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
[[ $? -ne 0 || -z "$ctid" ]] && return 1
|
||||
|
||||
@@ -196,18 +196,29 @@ disk_referenced_in_config() {
|
||||
|
||||
|
||||
|
||||
CT_LIST=$(pct list | awk 'NR>1 {print $1, $3}')
|
||||
CT_LIST=""
|
||||
OCI_NOTE=""
|
||||
CT_LIST_H=$UI_MENU_LIST_H
|
||||
while read -r ct_id ct_name; do
|
||||
[[ -n "$ct_id" ]] || continue
|
||||
if pmx_lxc_is_oci "$ct_id"; then
|
||||
CT_LIST_H=$((UI_MENU_LIST_H - 2))
|
||||
OCI_NOTE="\n\n$(translate "Containers created from an OCI image are not listed: their paths are changed in OCI manager Apps (Recreate).")"
|
||||
continue
|
||||
fi
|
||||
CT_LIST+="${CT_LIST:+ }$ct_id ${ct_name:-CT-$ct_id}"
|
||||
done < <(pct list | awk 'NR>1 {print $1, $3}')
|
||||
if [ -z "$CT_LIST" ]; then
|
||||
dialog --backtitle "$BACKTITLE" \
|
||||
--title "$(translate "Error")" \
|
||||
--msgbox "$(translate "No CTs available in the system.")" $UI_MSG_H $UI_MSG_W
|
||||
--msgbox "$(translate "No CTs available in the system.")${OCI_NOTE}" 12 $UI_MSG_W
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086 # CT_LIST is intentionally word-split into dialog menu pairs
|
||||
CTID=$(dialog --backtitle "$BACKTITLE" \
|
||||
--title "$(translate "Select CT for destination disk")" \
|
||||
--menu "$(translate "Select the CT to which you want to add disks:")" $UI_MENU_H $UI_MENU_W $UI_MENU_LIST_H \
|
||||
--menu "$(translate "Select the CT to which you want to add disks:")${OCI_NOTE}" $UI_MENU_H $UI_MENU_W $CT_LIST_H \
|
||||
$CT_LIST \
|
||||
2>&1 >/dev/tty)
|
||||
|
||||
|
||||
@@ -419,6 +419,13 @@ update_component_status() {
|
||||
# Hybrid Dialog Functions (Web/Terminal)
|
||||
# ============================================
|
||||
|
||||
# A container created from an OCI image declares its entrypoint (or cmd) in
|
||||
# its configuration. It has no package manager to install drivers with, and
|
||||
# OCI manager Apps is what changes its devices.
|
||||
pmx_lxc_is_oci() {
|
||||
grep -qaE '^(entrypoint|cmd):' "/etc/pve/lxc/${1}.conf" 2>/dev/null
|
||||
}
|
||||
|
||||
# Detect if running in web mode
|
||||
is_web_mode() {
|
||||
[[ "$EXECUTION_MODE" == "web" ]]
|
||||
|
||||
Reference in New Issue
Block a user