-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathDarwinKVM.sh
More file actions
executable file
·1726 lines (1481 loc) · 56.6 KB
/
DarwinKVM.sh
File metadata and controls
executable file
·1726 lines (1481 loc) · 56.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#
# DarwinKVM project's Main Menu Script.
#
# Copyright (c) 2025 RoyalGraphX
# Copyright (c) 2025 Carnations Botanica
# BSD 3-Clause License, see LICENSE for more information.
#
# No, you cannot use my EFI or XML configurations in your prebuilts or repackage any of the content here.
# All instances of related work, must point back to DarwinKVM if you use any information the project.
# See LICENSE for more information. This is your only warning. I want to stress that the entire point
# and time I spend on this project, is directly about teaching and helping with proper support.
# You will defeat the purpose of every hour of work i've spent, if you disobey these wishes.
#
# Script Variables
VERSION="0.1.5"
DEBUG=false
isInternalUser=false
l2c() {
local mode="$1"
shift
local message="$1"
case "$mode" in
INTRNL)
[[ "$isInternalUser" == true ]] && echo "[INTERNAL] $message"
;;
DBG)
[[ "$DEBUG" == true ]] && echo "[DEBUG] $message"
;;
esac
}
# Detect basic system details
ROOT=$(pwd) # This command is POSIX-compliant and should not fail, works on macOS, Linux, and Windows (in compatible shells)
case "$(uname -s)" in
Linux)
SHELL_NAME=$(basename "$SHELL")
ARCH=$(uname -m)
;;
Darwin)
SHELL_NAME=$(basename "$SHELL")
ARCH=$(uname -m)
;;
CYGWIN*|MINGW*|MSYS*)
# For Windows (Git Bash, MSYS, Cygwin)
# SHELL variable might not be reliably set, so we check the process name.
# Comspec is a reliable fallback for the default command prompt.
SHELL_NAME=${SHELL##*/}
if [ -z "$SHELL_NAME" ]; then
SHELL_NAME=${COMSPEC##*\\}
fi
# PROCESSOR_ARCHITECTURE is a reliable environment variable for architecture on Windows
if [ "$PROCESSOR_ARCHITECTURE" = "AMD64" ] || [ "$PROCESSOR_ARCHITECTURE" = "x64" ]; then
ARCH="x86_64"
elif [ "$PROCESSOR_ARCHITECTURE" = "x86" ]; then
ARCH="i686"
else
ARCH="unknown"
fi
;;
*)
# Fallback for generic Unix-like/enough systems
SHELL_NAME=$(basename "$SHELL")
ARCH=$(uname -m)
;;
esac
# Setup Submodule paths
DISKPROVISION="$ROOT/extras/DiskProvision"
DUDKFIRMWARE="$ROOT/extras/DUDK-Firmware"
DARWINFETCH="$ROOT/extras/DarwinFetch"
DARWINOCPKG="$ROOT/extras/DarwinOCPkg"
PROPERTREE="$ROOT/extras/ProperTree"
GENSMBIOS="$ROOT/extras/GenSMBIOS"
RPSGPUPT="$ROOT/extras/single-gpu-passthrough"
AVFIO="$ROOT/extras/vfio-script"
# List of submodules that are supposed to be available to DKVM right now
SUBMODULES=("$DISKPROVISION" "$DUDKFIRMWARE" "$DARWINFETCH" "$DARWINOCPKG" "$PROPERTREE" "$GENSMBIOS" "$RPSGPUPT" "$AVFIO")
# Determine amount of submodules that were found as valid paths
SUBMODULES_VALID=0 # Set the int as 0 as a setup
for path in "${SUBMODULES[@]}"; do # Iterate through submodules and check if they exist
if [[ -d "$path" ]]; then
((SUBMODULES_VALID++))
fi
done
# Detect OS
if [[ "$(uname)" == "Darwin" ]]; then
OS_NAME="$(sw_vers -productName) $(sw_vers -productVersion)"
elif [[ -f /etc/os-release ]]; then
# Extract OS ID and PRETTY_NAME
OS_ID=$(grep '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
OS_NAME_RAW=$(grep '^PRETTY_NAME=' /etc/os-release | cut -d= -f2 | tr -d '"')
# List of supported OSes
SUPPORTED_OSES=("arch" "fedora" "debian" "linuxmint" "ubuntu")
# Check if the detected OS is in the supported list
OS_SUPPORTED=false
for os in "${SUPPORTED_OSES[@]}"; do
if [[ "$OS_ID" == "$os" ]]; then
OS_SUPPORTED=true
break
fi
done
# Set OS_NAME accordingly
if [[ "$OS_SUPPORTED" == true ]]; then
OS_NAME="$OS_NAME_RAW"
else
OS_NAME="Unknown OS (Support cannot be expected!)"
fi
else
OS_NAME="Unknown OS (Support cannot be expected!)"
fi
# Construct the main menu
if [[ -e ".internal" ]]; then
DEBUG=true
isInternalUser=true
fi
# Conditionally define menu options based on the operating system
if [[ "$(uname)" == "Linux" ]]; then
# On Linux, show all options, including system-specific ones.
# Check status for RisingPrism sGPU Scripts
RPSGPU_REQUIRED_FILES=(
"/etc/systemd/system/libvirt-nosleep@.service"
"/usr/local/bin/vfio-startup"
"/usr/local/bin/vfio-teardown"
"/etc/libvirt/hooks/qemu"
)
RPSGPU_INSTALLED=true
for file in "${RPSGPU_REQUIRED_FILES[@]}"; do
if [[ ! -f "$file" ]]; then
RPSGPU_INSTALLED=false
break
fi
done
if [[ "$RPSGPU_INSTALLED" == true ]]; then
RPSGPU_MENU_TEXT="Uninstall RisingPrism sGPU Scripts"
else
RPSGPU_MENU_TEXT="Install RisingPrism sGPU Scripts"
fi
# Check status for akshaycodes VFIO-Script
AVFIO_REQUIRED_FILES=(
"/etc/systemd/system/libvirt-nosleep@.service"
"/etc/libvirt/hooks/qemu"
"/bin/vfio-script.sh"
)
AVFIO_INSTALLED=true
for file in "${AVFIO_REQUIRED_FILES[@]}"; do
if [[ ! -f "$file" ]]; then
AVFIO_INSTALLED=false
break
fi
done
if [[ "$AVFIO_INSTALLED" == true ]]; then
AVFIO_MENU_TEXT="Uninstall akshaycodes VFIO-Script"
else
AVFIO_MENU_TEXT="Install akshaycodes VFIO-Script"
fi
# Define the full list of options for Linux
MENU_OPTIONS=(
"Download/Update Submodules"
"System Report"
"Dump IOMMU Table"
"Dynamic XML Configuration"
"Import XML to Virt-Manager"
"Launch DiskProvision"
"Launch DarwinFetch"
"Launch ProperTree"
"Launch GenSMBIOS"
"$RPSGPU_MENU_TEXT"
"$AVFIO_MENU_TEXT"
"Modify QEMU Hook Script"
"List Passthrough Devices via lspci"
"Overclock via cpupower command"
)
else
# On non-Linux systems, show a reduced set of options
MENU_OPTIONS=(
"Download/Update Submodules"
"System Report"
"Launch DiskProvision"
"Launch DarwinFetch"
"Launch ProperTree"
"Launch GenSMBIOS"
)
fi
# Append carnationsinternal options if isInternalUser is true
if [[ "$isInternalUser" == true ]]; then
MENU_OPTIONS+=(
"Update Submodules for EUs (Rebase)"
"Create New Local Commit"
"Push Local Changes to Github"
"Repair Ruby Environment"
)
fi
# finally, add the Exit option
MENU_OPTIONS+=(
"Exit"
)
# Function to display the menu
show_menu() {
clear
l2c DBG "Root directory: $ROOT"
l2c DBG "Shell: $SHELL_NAME"
l2c DBG "Architecture: $ARCH"
if [[ "$isInternalUser" == true && "$DEBUG" == true ]]; then
echo "Welcome to DarwinKVM! [Internal User Options Enabled | Debug Mode Enabled]"
elif [[ "$isInternalUser" == true ]]; then
echo "Welcome to DarwinKVM! [Internal User Options Enabled]"
elif [[ "$DEBUG" == true ]]; then
echo "Welcome to DarwinKVM! [Debug Mode Enabled]"
else
echo "Welcome to DarwinKVM!"
fi
echo "Quickly and interactively run various commands and scripts."
echo "Copyright (c) 2023 2024 2025 RoyalGraphX"
echo "Copyright (c) 2025 Carnations Botanica"
echo "$SHELL_NAME $ARCH Pre-Release $VERSION for $OS_NAME"
if [[ $SUBMODULES_VALID -eq 0 ]]; then
echo "No valid submodules found! Please select option 1 before continuing."
elif [[ $SUBMODULES_VALID -ge 8 ]]; then
echo "All $SUBMODULES_VALID submodules are valid and found!"
else
echo "Valid submodules found: $SUBMODULES_VALID (Some features may not work correctly.)"
fi
echo ""
echo "WARNING: When it comes to automation, lots of options will use sudo!"
echo "If this is something you do not feel comfortable with, do it manually."
echo ""
echo "Main Menu:"
echo ""
# Loop through options dynamically, future proofing new options
for i in "${!MENU_OPTIONS[@]}"; do
echo "$((i + 1)). ${MENU_OPTIONS[i]}"
done
echo ""
echo "Select an option (1-${#MENU_OPTIONS[@]})"
}
# Function to ensure all submodules are setup and valid
setupsubmods() {
clear
echo "Checking submodules..."
# Ensure we are in a Git repository, and not a ZIP download
if [[ ! -d .git ]]; then
echo "Error: This is not a Git repository. Did you download as ZIP?"
echo "Ensure you are using 'git clone' in your terminal to download DarwinKVM."
return 1
fi
# Check if submodules are already initialized
if [[ -f .gitmodules ]]; then
echo "Updating submodules..."
git submodule update --init --recursive
if [[ $? -eq 0 ]]; then
echo "Submodules updated successfully."
else
echo "Error: Failed to update submodules. Please check your Git setup."
return 1
fi
else
echo "No submodules found in .gitmodules. Creating the required submodules."
# Add the currently required submodules
git submodule add https://github.com/royalgraphx/DiskProvision.git extras/DiskProvision
git submodule add https://github.com/royalgraphx/DUDK-Firmware.git extras/DUDK-Firmware
git submodule add https://github.com/royalgraphx/DarwinFetch.git extras/DarwinFetch
git submodule add https://github.com/royalgraphx/DarwinOCPkg.git extras/DarwinOCPkg
git submodule add https://github.com/corpnewt/ProperTree.git extras/ProperTree
git submodule add https://github.com/corpnewt/GenSMBIOS.git extras/GenSMBIOS
git submodule add https://gitlab.com/risingprismtv/single-gpu-passthrough.git extras/single-gpu-passthrough
git submodule add https://gitlab.com/akshaycodes/vfio-script.git extras/vfio-script
# Initialize and update the repository/submodules
git submodule update --init --recursive
if [[ $? -eq 0 ]]; then
echo "Submodules are now setup!"
else
echo "Error: Failed to initialize submodules. Please check your Git setup."
return 1
fi
fi
}
# Function to check the host status and report its current states
sysreport() {
clear
echo "This option is still not available."
}
# Function to dump IOMMU Table into groups and sort them neatly
iommu() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "IOMMU Table dumping is only supported on Linux hosts."
return 1
fi
# Check if IOMMU is enabled by looking for relevant kernel messages
if ! sudo dmesg | grep -E "iommu"&> /dev/null; then
echo "Warning: IOMMU does not appear to be enabled on this system."
read -rp "Press Enter to continue anyway, or Ctrl+C to exit..."
fi
# Run the script using the detected shell
"$SHELL_NAME" ./scripts/iommu.sh
}
# The DarwinKVM XML Importer
xmlimporter() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "Importing XMLs is only supported on Linux hosts."
return 1
fi
XML_DIR="$ROOT/xmls"
# Check if the directory exists
if [[ ! -d "$XML_DIR" ]]; then
echo "No XML directory found at $XML_DIR."
return 1
fi
# Find all .xml files
xml_files=()
while IFS= read -r -d '' file; do
xml_files+=("$file")
done < <(find "$XML_DIR" -maxdepth 1 -type f -name "*.xml" -print0)
# Check if any XML files were found
if [[ ${#xml_files[@]} -eq 0 ]]; then
echo "No XML files found in $XML_DIR."
return 1
fi
echo "Available XML files:"
for i in "${!xml_files[@]}"; do
echo "$((i+1)). ${xml_files[$i]##*/}" # Display filename only
done
# Prompt user for selection
read -rp "Enter the number of the XML file to import: " choice
# Validate input
if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#xml_files[@]} )); then
echo "Invalid selection. Returning to main menu..."
return 1
fi
# Echo the chosen file
selected_file="${xml_files[$((choice-1))]}"
echo "You chose to import: $selected_file"
# Extract the VM name from the XML using a portable approach
if [[ "$(uname)" == "Darwin" ]]; then
# For macOS, use sed to extract the name
vm_name=$(sed -n 's/.*<name>\([^<]*\)<\/name>.*/\1/p' "$selected_file")
else
# For Linux, use grep and sed (same as before for Linux)
vm_name=$(grep -o '<name>[^<]*</name>' "$selected_file" | sed 's/<[^>]*>//g')
fi
if [[ -z "$vm_name" ]]; then
echo "No <name> tag found in the XML file."
return 1
fi
echo "The VM name defined in the XML is: $vm_name"
# Attempt to use virsh to check if the VM already exists
if sudo virsh dumpxml "$vm_name" &>/dev/null; then
echo "VM '$vm_name' already exists. Cannot import a duplicate XML."
return 1
else
echo "VM '$vm_name' does not exist. You can import it if you choose to."
fi
# Prompt user to confirm import to virt-manager
read -rp "Do you want to import this VM to virt-manager? (y/N): " user_input
user_input=$(echo "$user_input" | tr '[:upper:]' '[:lower:]') # Normalize to lowercase
if [[ "$user_input" == "y" || "$user_input" == "yes" ]]; then
# Import the XML to virt-manager using virsh define
if sudo virsh --connect qemu:///system define "$selected_file"; then
echo "VM '$vm_name' has been successfully imported to virt-manager."
else
echo "Failed to import VM '$vm_name'."
return 1
fi
else
echo "Import cancelled. Returning to main menu..."
fi
}
# Function to bootstrap and launch DiskProvision
bootstrap_diskprovision() {
clear
echo "Bootstrapping DiskProvision..."
# Try to locate Python (prefer python3, fallback to python)
PYTHON_CMD=$(command -v python3 || command -v python)
if [[ -z "$PYTHON_CMD" ]]; then
echo "Error: Python is not installed. Please install Python to continue."
return 1
fi
echo "Using Python from: $PYTHON_CMD"
# Get the Python version
PYTHON_VERSION=$("$PYTHON_CMD" --version 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to retrieve Python version."
return 1
fi
echo "Python version: $PYTHON_VERSION"
# Construct the DiskProvision root path using $ROOT
DP_ROOT="$ROOT/extras/DiskProvision"
if [[ ! -d "$DP_ROOT" ]]; then
echo "Error: DiskProvision directory not found at $DP_ROOT"
echo "Please ensure the DiskProvision submodule is downloaded."
return 1
fi
echo "DiskProvision directory found at: $DP_ROOT"
# Launch DiskProvision.sh in a new shell process and wait for it to exit
echo "DiskProvision bootstrap complete! Now launching..."
(
cd "$DP_ROOT" || { echo "Error: Failed to change directory to $DP_ROOT."; exit 1; }
# Execute the DiskProvision.sh script in a new shell
exec "$SHELL_NAME" DiskProvision.sh
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: DiskProvision process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "DiskProvision process completed successfully."
}
# Function to bootstrap and launch DarwinFetch
bootstrap_darwinfetch() {
clear
echo "Bootstrapping DarwinFetch..."
# Try to locate Python (prefer python3, fallback to python)
PYTHON_CMD=$(command -v python3 || command -v python)
if [[ -z "$PYTHON_CMD" ]]; then
echo "Error: Python is not installed. Please install Python to continue."
return 1
fi
echo "Using Python from: $PYTHON_CMD"
# Get the Python version
PYTHON_VERSION=$("$PYTHON_CMD" --version 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to retrieve Python version."
return 1
fi
echo "Python version: $PYTHON_VERSION"
# Construct the DarwinFetch root path using $ROOT
DF_ROOT="$ROOT/extras/DarwinFetch"
if [[ ! -d "$DF_ROOT" ]]; then
echo "Error: DarwinFetch directory not found at $DF_ROOT."
echo "Please ensure the DarwinFetch submodule is downloaded."
return 1
fi
echo "DarwinFetch directory found at: $DF_ROOT"
# Launch DarwinFetch.sh in a new shell process and wait for it to exit
echo "DarwinFetch bootstrap complete! Now launching..."
(
cd "$DF_ROOT" || { echo "Error: Failed to change directory to $DF_ROOT."; exit 1; }
# Execute the DarwinFetch.sh script in a new shell
exec "$SHELL_NAME" DarwinFetch.sh
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: DarwinFetch process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "DarwinFetch process completed successfully."
}
# Function to bootstrap and launch ProperTree
bootstrap_propertree() {
clear
echo "Bootstrapping ProperTree..."
# Try to locate Python (prefer python3, fallback to python)
PYTHON_CMD=$(command -v python3 || command -v python)
if [[ -z "$PYTHON_CMD" ]]; then
echo "Error: Python is not installed. Please install Python to continue."
return 1
fi
echo "Using Python from: $PYTHON_CMD"
# Get the Python version
PYTHON_VERSION=$("$PYTHON_CMD" --version 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to retrieve Python version."
return 1
fi
echo "Python version: $PYTHON_VERSION"
# Check for tkinter module
echo "Checking for tkinter support..."
"$PYTHON_CMD" -c "import tkinter" 2>/dev/null
if [[ $? -ne 0 ]]; then
echo "Error: tkinter module is not available in this Python installation."
echo "Please install tkinter. For example:"
echo " On Ubuntu/Debian: sudo apt-get install python3-tk"
echo " On Arch Linux: sudo pacman -S tk"
return 1
fi
echo "tkinter module is available."
# Construct the ProperTree root path using $ROOT
PT_ROOT="$ROOT/extras/ProperTree"
if [[ ! -d "$PT_ROOT" ]]; then
echo "Error: ProperTree directory not found at $PT_ROOT."
echo "Please ensure the ProperTree submodule is downloaded."
return 1
fi
echo "ProperTree directory found at: $PT_ROOT"
# Launch ProperTree.py and wait for it to exit
echo "ProperTree bootstrap complete! Now launching..."
(
cd "$PT_ROOT" || { echo "Error: Failed to change directory to $PT_ROOT."; exit 1; }
# Execute the ProperTree.py script
exec $PYTHON_CMD ProperTree.py
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: ProperTree process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "ProperTree process completed successfully."
}
# Function to bootstrap and launch GenSMBIOS
bootstrap_gensmbios() {
clear
echo "Bootstrapping GenSMBIOS..."
# Try to locate Python (prefer python3, fallback to python)
PYTHON_CMD=$(command -v python3 || command -v python)
if [[ -z "$PYTHON_CMD" ]]; then
echo "Error: Python is not installed. Please install Python to continue."
return 1
fi
echo "Using Python from: $PYTHON_CMD"
# Get the Python version
PYTHON_VERSION=$("$PYTHON_CMD" --version 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to retrieve Python version."
return 1
fi
echo "Python version: $PYTHON_VERSION"
# Construct the GenSMBIOS root path using $ROOT
GSMB_ROOT="$ROOT/extras/GenSMBIOS"
if [[ ! -d "$GSMB_ROOT" ]]; then
echo "Error: GenSMBIOS directory not found at $GSMB_ROOT."
echo "Please ensure the GenSMBIOS submodule is downloaded."
return 1
fi
echo "GenSMBIOS directory found at: $GSMB_ROOT"
# Launch GenSMBIOS.py and wait for it to exit
echo "GenSMBIOS bootstrap complete! Now launching..."
(
cd "$GSMB_ROOT" || { echo "Error: Failed to change directory to $GSMB_ROOT."; exit 1; }
# Execute the ProperTree.py script
exec $PYTHON_CMD GenSMBIOS.py
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: GenSMBIOS process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "GenSMBIOS process completed successfully."
}
# Function to install/uninstall RisingPrism Single GPU passthrough
modify_rpsgpu() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "Installing RisingPrism GPU scripts is only supported on Linux hosts."
return 1
fi
echo "Checking installation status of RisingPrism Single GPU passthrough..."
echo ""
# Construct the single-gpu-passthrough root path using $ROOT
RPSGPUPT_ROOT="$ROOT/extras/single-gpu-passthrough"
if [[ ! -d "$RPSGPUPT_ROOT" ]]; then
echo "Error: single-gpu-passthrough directory not found at $RPSGPUPT_ROOT."
echo "Please ensure the single-gpu-passthrough submodule is downloaded."
return 1
fi
echo "single-gpu-passthrough directory found at: $RPSGPUPT_ROOT"
REQUIRED_FILES=(
"/etc/systemd/system/libvirt-nosleep@.service"
"/usr/local/bin/vfio-startup"
"/usr/local/bin/vfio-teardown"
"/etc/libvirt/hooks/qemu"
)
ALL_FOUND=true
for file in "${REQUIRED_FILES[@]}"; do
if [[ -f "$file" ]]; then
echo "Successfully Found: $file"
else
echo "Missing: $file"
ALL_FOUND=false
fi
done
echo ""
if [[ "$ALL_FOUND" == true ]]; then
echo "All files are present."
echo "Routing to uninstallation process..."
# List the required files that will be removed
echo "The following files will be removed:"
for file in "${REQUIRED_FILES[@]}"; do
echo " $file"
done
echo ""
# Prompt the user for confirmation (default is No)
read -rp "Are you sure you want to delete these files? (y/N): " confirmation
# Convert response to lowercase for consistency
confirmation=${confirmation,,}
if [[ "$confirmation" == "y" || "$confirmation" == "yes" ]]; then
echo "Removing files..."
for file in "${REQUIRED_FILES[@]}"; do
# Use sudo to remove each file or directory
sudo rm -rf "$file"
if [[ $? -eq 0 ]]; then
echo "Removed: $file"
else
echo "Failed to remove: $file"
echo "Ensure you delete the file manually."
fi
done
echo "Uninstallation process completed."
else
echo "Uninstallation cancelled."
fi
else
echo "Routing to installation process..."
# Launch install_hooks.sh in a new shell process and wait for it to exit
(
cd "$RPSGPUPT_ROOT" || { echo "Error: Failed to change directory to $RPSGPUPT_ROOT."; exit 1; }
# Ensure the install_hooks.sh script is executable
chmod +x install_hooks.sh
# Execute the install_hooks.sh script in a new shell w sudo
exec sudo "$SHELL_NAME" ./install_hooks.sh
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: install_hooks.sh process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "Installation process completed."
fi
}
# Function to install/uninstall akshaycodes VFIO-Script
modify_avfio() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "Installing akshaycodes VFIO script is only supported on Linux hosts."
return 1
fi
echo "Checking installation status of akshaycodes VFIO-Script..."
echo ""
# Construct the vfio-script root path using $ROOT
AVFIO_ROOT="$ROOT/extras/vfio-script"
if [[ ! -d "$AVFIO_ROOT" ]]; then
echo "Error: vfio-script directory not found at $AVFIO_ROOT."
echo "Please ensure the vfio-script submodule is downloaded."
return 1
fi
echo "vfio-script directory found at: $AVFIO_ROOT"
REQUIRED_FILES=(
"/etc/systemd/system/libvirt-nosleep@.service"
"/etc/libvirt/hooks/qemu"
"/bin/vfio-script.sh"
)
ALL_FOUND=true
for file in "${REQUIRED_FILES[@]}"; do
if [[ -f "$file" ]]; then
echo "Successfully Found: $file"
else
echo "Missing: $file"
ALL_FOUND=false
fi
done
echo ""
if [[ "$ALL_FOUND" == true ]]; then
echo "All files are present."
echo "Routing to uninstallation process..."
# List the required files that will be removed
echo "The following files will be removed:"
for file in "${REQUIRED_FILES[@]}"; do
echo " $file"
done
echo ""
# Prompt the user for confirmation (default is No)
read -rp "Are you sure you want to delete these files? (y/N): " confirmation
# Convert response to lowercase for consistency
confirmation=${confirmation,,}
if [[ "$confirmation" == "y" || "$confirmation" == "yes" ]]; then
echo "Removing files..."
for file in "${REQUIRED_FILES[@]}"; do
# Use sudo to remove each file or directory
sudo rm -rf "$file"
if [[ $? -eq 0 ]]; then
echo "Removed: $file"
else
echo "Failed to remove: $file"
echo "Ensure you delete the file manually."
fi
done
echo "Uninstallation process completed."
else
echo "Uninstallation cancelled."
fi
else
echo "Routing to installation process..."
# Launch vfio_script_install.sh in a new shell process and wait for it to exit
(
cd "$AVFIO_ROOT" || { echo "Error: Failed to change directory to $AVFIO_ROOT."; exit 1; }
# Ensure the vfio_script_install.sh script is executable
chmod +x vfio_script_install.sh
# Execute the vfio_script_install.sh script in a new shell with sudo
exec sudo "$SHELL_NAME" ./vfio_script_install.sh
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: vfio_script_install.sh process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "Installation process completed."
fi
}
# Function that tries to use Nano, then Vim, finally Vi, to edit QEMU Hook script
modify_qemuhook() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "Modifying QEMU Hook script contents is only supported on Linux hosts."
return 1
fi
echo "Attempting to open QEMU hook script for editing..."
QEMU_HOOK_PATH="/etc/libvirt/hooks/qemu"
# Ensure the QEMU hook file exists
if [[ ! -f "$QEMU_HOOK_PATH" ]]; then
echo "Error: $QEMU_HOOK_PATH does not exist."
return 1
fi
# List of editors in priority order
EDITORS=("nano" "vim" "vi")
for editor in "${EDITORS[@]}"; do
if command -v "$editor" &> /dev/null; then
echo "Opening $QEMU_HOOK_PATH with $editor..."
sudo "$editor" "$QEMU_HOOK_PATH"
return $? # Exit after successful edit
fi
done
echo "Error: No suitable text editor (nano, vim, vi) found on the system."
return 1
echo "Opened and modified QEMU Hook script successfully."
}
# Function that isolates VGA/Audio devices from lspci output
list_pt_lspci() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "lspci dumping is only supported on Linux hosts."
return 1
fi
echo "Listing VGA, Audio, and USB Controller devices from lspci output..."
echo ""
# Check if lspci is available
if ! command -v lspci &> /dev/null; then
echo "Error: lspci command not found. Please install pciutils."
return 1
fi
# List VGA and Audio devices with relevant details
lspci_output=$(lspci -nn | grep -Ei 'vga|3d|audio|usb')
if [[ -z "$lspci_output" ]]; then
echo "No VGA, Audio, or USB Controller devices found."
return 1
fi
echo "$lspci_output"
echo ""
}
# Function to call cpupower.sh from scripts
oc_cpu_cpupower() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "lspci dumping is only supported on Linux hosts."
return 1
fi
# Construct the scripts root path using $ROOT
SCRIPTS_ROOT="$ROOT/scripts"
if [[ ! -d "$SCRIPTS_ROOT" ]]; then
echo "Error: Scripts directory not found at $SCRIPTS_ROOT"
echo "Please ensure the scripts folder exists."
return 1
fi
echo "Scripts directory found at: $SCRIPTS_ROOT"
# Launch cpupower.sh in a new shell process and wait for it to exit
(
cd "$SCRIPTS_ROOT" || { echo "Error: Failed to change directory to $SCRIPTS_ROOT."; exit 1; }
# Execute the cpupower.sh script in a new shell
exec "$SHELL_NAME" cpupower.sh
)
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "Error: cpupower process exited with error code $EXIT_CODE."
return $EXIT_CODE
fi
echo "cpupower process completed successfully."
}
# The DarwinKVM Dynamic XML Configurator
# Pulls host data to make unique XML like virt-man
dynamic_xml() {
clear
# Ensure the OS is Linux
if [[ "$(uname)" != "Linux" ]]; then
echo "Dynamic XML is only supported on Linux hosts."
return 1
fi
# XML content collector
XML_CONTENT=""
# Create the comment header for the XML
create_header() {
XML_CONTENT+="<!--\n"
XML_CONTENT+=" This virtual machine definition was created dynamically by DarwinKVM\n"
XML_CONTENT+=" The model of this XML is set to: ${MODEL}\n"
XML_CONTENT+="-->\n\n"
}
create_domain_wrapper() {
XML_CONTENT+="<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>\n"
}
# Very simple branding, yknow.
create_domain_details() {
XML_CONTENT+=" <name>DarwinKVM-${MODEL_PRETTY}</name>\n"
XML_CONTENT+=" <description>This virtual machine is a DarwinKVM ${MODEL} using ${GUESTCPU}.</description>\n"
XML_CONTENT+=" <uuid>$(uuidgen)</uuid>\n"
}
# I need to actually test if memoryBacking will automatically place itself after import
create_memory() {
XML_CONTENT+=" <memory unit='KiB'>$RESERVED_MEMORY_KIB</memory>\n"
XML_CONTENT+=" <currentMemory unit='KiB'>$RESERVED_MEMORY_KIB</currentMemory>\n"
XML_CONTENT+=" <memoryBacking>\n"
XML_CONTENT+=" <nosharepages/>\n"
XML_CONTENT+=" </memoryBacking>\n"
}
create_vcpus() {
XML_CONTENT+=" <vcpu placement='static'>$VCPUS</vcpu>\n"
}
create_os() {
# Ensure MODEL_PRETTY is set based on MODEL
if [[ "$MODEL" == "MacPro7,1" ]]; then
MODEL_PRETTY="MP71"
elif [[ "$MODEL" == "MacPro5,1" ]]; then
MODEL_PRETTY="MP51"
elif [[ "$MODEL" == "MacPro4,1" ]]; then
MODEL_PRETTY="MP41"
elif [[ "$MODEL" == "MacPro3,1" ]]; then
MODEL_PRETTY="MP31"
elif [[ "$MODEL" == "MacPro2,1" ]]; then
MODEL_PRETTY="MP21"
else
MODEL_PRETTY="Unknown"
fi
# Check which OVMF files exist, prioritize .4m.fd over others
if [[ -n "$OVMF_CODE" && -n "$OVMF_VARS" ]]; then
# Determine which OVMF code file to use
if [[ -f "$OVMF_CODE" && "$OVMF_CODE" =~ \.4m\.fd$ ]]; then
CODE_FILE="$OVMF_CODE"
EXTENSION="4m.fd"
elif [[ -f "$OVMF_CODE" && "$OVMF_CODE" =~ \.fd$ ]]; then
CODE_FILE="$OVMF_CODE"
EXTENSION="fd"
elif [[ -f "$OVMF_CODE" ]]; then
CODE_FILE="$OVMF_CODE"
EXTENSION="${OVMF_CODE##*.}"
l2c INTRNL "Using fallback OVMF_CODE file with extension: .$EXTENSION"
else
l2c INTRNL "OVMF_CODE not found or not a valid .fd variant."
return
fi