mirror of
https://github.com/OVERLORD7F/SVMU.git
synced 2025-10-01 21:52:47 +03:00
Compare commits
6 Commits
0df2fccc62
...
main
Author | SHA1 | Date | |
---|---|---|---|
8a45c99efb | |||
9592382966 | |||
754db8ff41 | |||
d6642c62f4 | |||
dfff6c74e6 | |||
22b746e7a8 |
@@ -7,7 +7,8 @@ Written in python, uses [SpaceVM API](https://spacevm.ru/docs/6.5/api/) to colle
|
|||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>_This utility is focused on managing virtual disks_<br>
|
>_This utility is focused on managing virtual disks_<br>
|
||||||
>_Works with SpaceVM 6.5.5 / 6.5.6 / 6.5.7_
|
>_Works with SpaceVM 6.5.5 / 6.5.6 / 6.5.7_ <br>
|
||||||
|
> [:file_folder:_Repo Mirror Available Here_:clipboard:](https://gt.7fproject.com/OVERLORD/SVMU)
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
- Fully setup SpaceVM cluster with VMs
|
- Fully setup SpaceVM cluster with VMs
|
||||||
@@ -17,8 +18,9 @@ Written in python, uses [SpaceVM API](https://spacevm.ru/docs/6.5/api/) to colle
|
|||||||
> Utility is only tested on Windows 10
|
> Utility is only tested on Windows 10
|
||||||
- For Windows 10 - [New Microsoft Terminal](https://github.com/microsoft/terminal) is highly recommended (correct colors, menus, etc)
|
- For Windows 10 - [New Microsoft Terminal](https://github.com/microsoft/terminal) is highly recommended (correct colors, menus, etc)
|
||||||
|
|
||||||
# Utility usage
|
# Utility usage options:
|
||||||
Clone repository or use compiled .exe from [Releases Tab](https://github.com/OVERLORD7F/SpaceVM_VM_Utility/releases)
|
+ Clone repository, run `main.py` using python
|
||||||
|
+ Use precompiled .exe from [Releases Tab](https://github.com/OVERLORD7F/SpaceVM_VM_Utility/releases)
|
||||||
|
|
||||||
## Config / Profile File
|
## Config / Profile File
|
||||||
Directory _./profiles_ contains all configured profiles with necessary data for utility.
|
Directory _./profiles_ contains all configured profiles with necessary data for utility.
|
||||||
|
BIN
assets/images/SVMU.ico
Normal file
BIN
assets/images/SVMU.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
assets/images/SVMU.png
Normal file
BIN
assets/images/SVMU.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@@ -53,7 +53,7 @@ def config_menu(base_url, api_key, config_relative_path):
|
|||||||
needs_reload = True
|
needs_reload = True
|
||||||
|
|
||||||
if sub_choice == "7":
|
if sub_choice == "7":
|
||||||
change_vm_uuids(config_relative_path)
|
change_vm_uuids(config_relative_path, base_url, api_key)
|
||||||
needs_reload = True
|
needs_reload = True
|
||||||
|
|
||||||
if sub_choice == "8":
|
if sub_choice == "8":
|
||||||
@@ -137,27 +137,24 @@ def config_import(config_relative_path):
|
|||||||
|
|
||||||
def change_startup_option(config_relative_path):
|
def change_startup_option(config_relative_path):
|
||||||
cls()
|
cls()
|
||||||
#console.print("[yellow bold]Skip start-up splash ?")
|
# Ask the user once and normalize the answer
|
||||||
new_value = Prompt.ask("[yellow bold]Skip start-up splash ?[/]", choices=["Y", "N"], default="N", case_sensitive=False)
|
new_value = Prompt.ask("[yellow bold]Skip start-up splash ?[/]", choices=["Y", "N"], default="N", case_sensitive=False)
|
||||||
if new_value == "Y" or new_value == "y":
|
if new_value.lower() == "y":
|
||||||
startup_option = "yes"
|
startup_option = "yes"
|
||||||
if new_value == "N" or new_value == "n":
|
else:
|
||||||
startup_option = "no"
|
|
||||||
new_value = Prompt.ask("[yellow bold]Skip start-up splash ?[/]", choices=["Y", "N"], default="N", case_sensitive=False)
|
|
||||||
if new_value == "Y" or new_value == "y":
|
|
||||||
startup_option = "yes"
|
|
||||||
if new_value == "N" or new_value == "n":
|
|
||||||
startup_option = "no"
|
startup_option = "no"
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(config_relative_path)
|
config.read(config_relative_path)
|
||||||
if config.has_section('General'):
|
# Ensure General section exists so we can write the option
|
||||||
config.set('General', 'skip_startup_splash', startup_option)
|
if not config.has_section('General'):
|
||||||
config.set('General', 'skip_startup_splash', startup_option)
|
config.add_section('General')
|
||||||
with open(config_relative_path, 'w') as config_file:
|
|
||||||
config.write(config_file)
|
config.set('General', 'skip_startup_splash', startup_option)
|
||||||
console.print(f"[green bold]Option set to: {new_value}")
|
with open(config_relative_path, 'w') as config_file:
|
||||||
else:
|
config.write(config_file)
|
||||||
console.print("[red bold]No section 'General' in config file")
|
|
||||||
|
console.print(f"[green bold]Option set to: {new_value}")
|
||||||
|
|
||||||
def change_data_pool(base_url, api_key, config_relative_path): #change selected data pool in config
|
def change_data_pool(base_url, api_key, config_relative_path): #change selected data pool in config
|
||||||
cls()
|
cls()
|
||||||
@@ -186,7 +183,7 @@ def change_iso_uuid(config_relative_path):
|
|||||||
print("No 'VM_Options' section in config file..")
|
print("No 'VM_Options' section in config file..")
|
||||||
config_show(config_relative_path)
|
config_show(config_relative_path)
|
||||||
|
|
||||||
def change_vm_uuids(config_relative_path): #change selected VM uuids in config
|
def change_vm_uuids(config_relative_path, base_url, api_key): #change selected VM uuids in config
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(config_relative_path)
|
config.read(config_relative_path)
|
||||||
# Remove old VM_List section if it exists, then add a fresh one
|
# Remove old VM_List section if it exists, then add a fresh one
|
||||||
@@ -200,6 +197,11 @@ def change_vm_uuids(config_relative_path): #change selected VM uuids in config
|
|||||||
vm_input = console.input("[bold yellow]>> [/]" )
|
vm_input = console.input("[bold yellow]>> [/]" )
|
||||||
if not vm_input:
|
if not vm_input:
|
||||||
break
|
break
|
||||||
|
# validate only the entered VM UUID via get_vm_name
|
||||||
|
vm_name = get_vm_name(base_url, "jwt " + api_key, vm_input)
|
||||||
|
if not vm_name:
|
||||||
|
console.print("[red bold]Invalid VM UUID (not found)")
|
||||||
|
continue
|
||||||
x += 1
|
x += 1
|
||||||
config.set('VM_List', f'uuid_{x}', vm_input)
|
config.set('VM_List', f'uuid_{x}', vm_input)
|
||||||
|
|
||||||
@@ -211,56 +213,6 @@ def change_vm_uuids(config_relative_path): #change selected VM uuids in config
|
|||||||
config_show(config_relative_path)
|
config_show(config_relative_path)
|
||||||
|
|
||||||
|
|
||||||
def config_edit(config_relative_path):
|
|
||||||
read_input = Prompt.ask("[bold yellow]Create new config file?[/]", choices=["Y", "N"], default="N", case_sensitive=False)
|
|
||||||
menu_choice = str(read_input)
|
|
||||||
if menu_choice == "Y" or menu_choice == "y":
|
|
||||||
base_url = input("Type SpaceVM Controller IP: ")
|
|
||||||
while check_ping(base_url) != True:
|
|
||||||
base_url = console.input("[bold red]No response.\nCheck and type SpaceVM Controller IP again: [/]")
|
|
||||||
|
|
||||||
api_key = input("Type your API Key: ")
|
|
||||||
while check_api_key(base_url, "jwt " + api_key) != 200:
|
|
||||||
api_key = console.input("[bold red]Check and type SpaceVM Controller API Key again: [/]")
|
|
||||||
show_data_pools(base_url, "jwt " + api_key)
|
|
||||||
data_pool_uuid = input("Type Data Pool UUID you wish to use: ")
|
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config["General"] = {
|
|
||||||
"controller_ip": base_url,
|
|
||||||
"api_key": api_key,
|
|
||||||
"skip_startup_splash": "no",
|
|
||||||
}
|
|
||||||
config["Data_Pool"] = {"data_pool_uuid": data_pool_uuid}
|
|
||||||
|
|
||||||
#disk_interface=input("Specify preffered disk interface (virtio / ide / scsi / sata): ")
|
|
||||||
#preallocation=input("Specify allocation type for virtual disks (none / falloc / full / metadata): ")
|
|
||||||
#iso_uuid=input("Specify ISO uuid you wish to auto-mount during operations(none - skip this step): ")
|
|
||||||
#config["VM_Options"] = {
|
|
||||||
# "disk_interface": disk_interface,
|
|
||||||
# "preallocation": preallocation,
|
|
||||||
# "iso_uuid": iso_uuid
|
|
||||||
#}
|
|
||||||
|
|
||||||
with open(config_relative_path, "w") as configfile: #writing everything from above to config file
|
|
||||||
config.write(configfile)
|
|
||||||
|
|
||||||
print("Type VM UUIDs one by one (input ENTER to stop)")
|
|
||||||
with open(config_relative_path, "a") as file:
|
|
||||||
file.write("[VM_List]\n") #manually writing section for VMs
|
|
||||||
vm_input = []
|
|
||||||
x = 0
|
|
||||||
while vm_input != "":
|
|
||||||
vm_input = input(">> ")
|
|
||||||
if vm_input:
|
|
||||||
x += 1
|
|
||||||
file.write(f"uuid_{x} = {vm_input}\n")
|
|
||||||
|
|
||||||
console.print("[green bold]VM UUIDs have been written in config :pencil:")
|
|
||||||
console.print("[green bold]Configuration completed ! :white_check_mark:")
|
|
||||||
Prompt.ask("[green_yellow bold]Press ENTER to proceed.. :right_arrow_curving_down:")
|
|
||||||
cls()
|
|
||||||
|
|
||||||
def check_config(config_relative_path):
|
def check_config(config_relative_path):
|
||||||
"""Check if config exists and is valid"""
|
"""Check if config exists and is valid"""
|
||||||
# Only check if the file is empty and needs to be removed
|
# Only check if the file is empty and needs to be removed
|
||||||
@@ -341,6 +293,11 @@ def create_new_profile():
|
|||||||
vm_input = console.input("[bold yellow]>> [/]")
|
vm_input = console.input("[bold yellow]>> [/]")
|
||||||
if not vm_input:
|
if not vm_input:
|
||||||
break
|
break
|
||||||
|
# validate only the vm_input by fetching VM name
|
||||||
|
vm_name = get_vm_name(base_url, "jwt " + api_key, vm_input)
|
||||||
|
if not vm_name:
|
||||||
|
console.print("[red bold]Invalid VM UUID (not found)")
|
||||||
|
continue
|
||||||
x += 1
|
x += 1
|
||||||
file.write(f"uuid_{x} = {vm_input}\n")
|
file.write(f"uuid_{x} = {vm_input}\n")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user