virtui-manager 1.1.5__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {virtui_manager-1.1.5.dist-info → virtui_manager-1.3.0.dist-info}/METADATA +1 -1
- virtui_manager-1.3.0.dist-info/RECORD +73 -0
- vmanager/constants.py +737 -108
- vmanager/dialog.css +24 -0
- vmanager/firmware_manager.py +4 -1
- vmanager/i18n.py +32 -0
- vmanager/libvirt_utils.py +132 -3
- vmanager/locales/de/LC_MESSAGES/virtui-manager.po +3012 -0
- vmanager/locales/fr/LC_MESSAGES/virtui-manager.mo +0 -0
- vmanager/locales/fr/LC_MESSAGES/virtui-manager.po +3124 -0
- vmanager/locales/it/LC_MESSAGES/virtui-manager.po +3012 -0
- vmanager/locales/virtui-manager.pot +3012 -0
- vmanager/modals/bulk_modals.py +13 -12
- vmanager/modals/cache_stats_modal.py +6 -5
- vmanager/modals/capabilities_modal.py +133 -0
- vmanager/modals/config_modal.py +25 -24
- vmanager/modals/cpu_mem_pc_modals.py +22 -21
- vmanager/modals/custom_migration_modal.py +10 -9
- vmanager/modals/disk_pool_modals.py +60 -59
- vmanager/modals/host_dashboard_modal.py +137 -0
- vmanager/modals/howto_disk_modal.py +13 -72
- vmanager/modals/howto_network_modal.py +13 -39
- vmanager/modals/howto_overlay_modal.py +13 -52
- vmanager/modals/howto_ssh_modal.py +12 -67
- vmanager/modals/howto_virtiofs_modal.py +13 -64
- vmanager/modals/input_modals.py +11 -10
- vmanager/modals/log_modal.py +2 -1
- vmanager/modals/migration_modals.py +20 -18
- vmanager/modals/network_modals.py +45 -36
- vmanager/modals/provisioning_modals.py +56 -56
- vmanager/modals/select_server_modals.py +8 -7
- vmanager/modals/selection_modals.py +7 -6
- vmanager/modals/server_modals.py +24 -23
- vmanager/modals/server_prefs_modals.py +103 -87
- vmanager/modals/utils_modals.py +10 -9
- vmanager/modals/virsh_modals.py +3 -2
- vmanager/modals/virtiofs_modals.py +6 -5
- vmanager/modals/vm_type_info_modal.py +2 -1
- vmanager/modals/vmanager_modals.py +19 -19
- vmanager/modals/vmcard_dialog.py +57 -57
- vmanager/modals/vmdetails_modals.py +115 -123
- vmanager/modals/xml_modals.py +3 -2
- vmanager/network_manager.py +4 -1
- vmanager/storage_manager.py +182 -42
- vmanager/utils.py +39 -6
- vmanager/vm_actions.py +28 -24
- vmanager/vm_queries.py +67 -25
- vmanager/vm_service.py +8 -5
- vmanager/vmanager.css +46 -0
- vmanager/vmanager.py +178 -112
- vmanager/vmcard.py +161 -159
- vmanager/webconsole_manager.py +21 -21
- virtui_manager-1.1.5.dist-info/RECORD +0 -65
- {virtui_manager-1.1.5.dist-info → virtui_manager-1.3.0.dist-info}/WHEEL +0 -0
- {virtui_manager-1.1.5.dist-info → virtui_manager-1.3.0.dist-info}/entry_points.txt +0 -0
- {virtui_manager-1.1.5.dist-info → virtui_manager-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {virtui_manager-1.1.5.dist-info → virtui_manager-1.3.0.dist-info}/top_level.txt +0 -0
vmanager/vmcard.py
CHANGED
|
@@ -53,8 +53,9 @@ from .utils import (
|
|
|
53
53
|
remote_viewer_cmd,
|
|
54
54
|
)
|
|
55
55
|
from .constants import (
|
|
56
|
-
ButtonLabels,
|
|
57
|
-
SparklineLabels, ErrorMessages, DialogMessages, VmAction
|
|
56
|
+
ButtonLabels, TabTitles, StatusText,
|
|
57
|
+
SparklineLabels, ErrorMessages, DialogMessages, VmAction,
|
|
58
|
+
WarningMessages, SuccessMessages
|
|
58
59
|
)
|
|
59
60
|
|
|
60
61
|
class VMCardActions(Static):
|
|
@@ -63,29 +64,29 @@ class VMCardActions(Static):
|
|
|
63
64
|
super().__init__()
|
|
64
65
|
|
|
65
66
|
def compose(self):
|
|
66
|
-
self.card.ui[
|
|
67
|
-
self.card.ui[
|
|
68
|
-
self.card.ui[
|
|
69
|
-
self.card.ui[
|
|
70
|
-
self.card.ui[
|
|
71
|
-
self.card.ui[
|
|
72
|
-
self.card.ui[
|
|
73
|
-
self.card.ui[
|
|
67
|
+
self.card.ui["start"] = Button(ButtonLabels.START, id="start", variant="success")
|
|
68
|
+
self.card.ui["shutdown"] = Button(ButtonLabels.SHUTDOWN, id="shutdown", variant="primary")
|
|
69
|
+
self.card.ui["stop"] = Button(ButtonLabels.FORCE_OFF, id="stop", variant="error")
|
|
70
|
+
self.card.ui["pause"] = Button(ButtonLabels.PAUSE, id="pause", variant="primary")
|
|
71
|
+
self.card.ui["resume"] = Button(ButtonLabels.RESUME, id="resume", variant="success")
|
|
72
|
+
self.card.ui["configure-button"] = Button(ButtonLabels.CONFIGURE, id="configure-button", variant="primary")
|
|
73
|
+
self.card.ui["web_console"] = Button(ButtonLabels.WEB_CONSOLE, id="web_console", variant="default")
|
|
74
|
+
self.card.ui["connect"] = Button(ButtonLabels.CONNECT, id="connect", variant="default")
|
|
74
75
|
|
|
75
|
-
self.card.ui[
|
|
76
|
-
self.card.ui[
|
|
77
|
-
self.card.ui[
|
|
76
|
+
self.card.ui["snapshot_take"] = Button(ButtonLabels.SNAPSHOT, id="snapshot_take", variant="primary")
|
|
77
|
+
self.card.ui["snapshot_restore"] = Button(ButtonLabels.RESTORE_SNAPSHOT, id="snapshot_restore", variant="primary")
|
|
78
|
+
self.card.ui["snapshot_delete"] = Button(ButtonLabels.DELETE_SNAPSHOT, id="snapshot_delete", variant="error")
|
|
78
79
|
|
|
79
|
-
self.card.ui[
|
|
80
|
-
self.card.ui[
|
|
81
|
-
self.card.ui[
|
|
82
|
-
self.card.ui[
|
|
83
|
-
self.card.ui[
|
|
80
|
+
self.card.ui["delete"] = Button(ButtonLabels.DELETE, id="delete", variant="error", classes="delete-button")
|
|
81
|
+
self.card.ui["clone"] = Button(ButtonLabels.CLONE, id="clone", classes="clone-button")
|
|
82
|
+
self.card.ui["migration"] = Button(ButtonLabels.MIGRATION, id="migration", variant="primary", classes="migration-button")
|
|
83
|
+
self.card.ui["xml"] = Button(ButtonLabels.VIEW_XML, id="xml")
|
|
84
|
+
self.card.ui["rename-button"] = Button(ButtonLabels.RENAME, id="rename-button", variant="primary", classes="rename-button")
|
|
84
85
|
|
|
85
|
-
self.card.ui[
|
|
86
|
-
self.card.ui[
|
|
87
|
-
self.card.ui[
|
|
88
|
-
self.card.ui[
|
|
86
|
+
self.card.ui["create_overlay"] = Button(ButtonLabels.CREATE_OVERLAY, id="create_overlay", variant="primary")
|
|
87
|
+
self.card.ui["commit_disk"] = Button(ButtonLabels.COMMIT_DISK, id="commit_disk", variant="error")
|
|
88
|
+
self.card.ui["discard_overlay"] = Button(ButtonLabels.DISCARD_OVERLAY, id="discard_overlay", variant="error")
|
|
89
|
+
self.card.ui["snap_overlay_help"] = Button(ButtonLabels.SNAP_OVERLAY_HELP, id="snap_overlay_help", variant="default")
|
|
89
90
|
|
|
90
91
|
self.card.ui["tabbed_content"] = TabbedContent(id="button-container")
|
|
91
92
|
|
|
@@ -93,37 +94,37 @@ class VMCardActions(Static):
|
|
|
93
94
|
with TabPane(TabTitles.MANAGE, id="manage-tab"):
|
|
94
95
|
with Horizontal():
|
|
95
96
|
with Vertical():
|
|
96
|
-
yield self.card.ui[
|
|
97
|
-
yield self.card.ui[
|
|
98
|
-
yield self.card.ui[
|
|
99
|
-
yield self.card.ui[
|
|
100
|
-
yield self.card.ui[
|
|
97
|
+
yield self.card.ui["start"]
|
|
98
|
+
yield self.card.ui["shutdown"]
|
|
99
|
+
yield self.card.ui["stop"]
|
|
100
|
+
yield self.card.ui["pause"]
|
|
101
|
+
yield self.card.ui["resume"]
|
|
101
102
|
with Vertical():
|
|
102
|
-
yield self.card.ui[
|
|
103
|
-
yield self.card.ui[
|
|
104
|
-
yield self.card.ui[
|
|
103
|
+
yield self.card.ui["configure-button"]
|
|
104
|
+
yield self.card.ui["web_console"]
|
|
105
|
+
yield self.card.ui["connect"]
|
|
105
106
|
with TabPane(self.card._get_snapshot_tab_title(num_snapshots=0), id="snapshot-tab"):
|
|
106
107
|
with Horizontal():
|
|
107
108
|
with Vertical():
|
|
108
|
-
yield self.card.ui[
|
|
109
|
-
yield self.card.ui[
|
|
110
|
-
yield self.card.ui[
|
|
109
|
+
yield self.card.ui["snapshot_take"]
|
|
110
|
+
yield self.card.ui["snapshot_restore"]
|
|
111
|
+
yield self.card.ui["snapshot_delete"]
|
|
111
112
|
with Vertical():
|
|
112
|
-
yield self.card.ui[
|
|
113
|
-
yield self.card.ui[
|
|
114
|
-
yield self.card.ui[
|
|
115
|
-
yield self.card.ui[
|
|
113
|
+
yield self.card.ui["create_overlay"]
|
|
114
|
+
yield self.card.ui["commit_disk"]
|
|
115
|
+
yield self.card.ui["discard_overlay"]
|
|
116
|
+
yield self.card.ui["snap_overlay_help"]
|
|
116
117
|
with TabPane(TabTitles.OTHER, id="special-tab"):
|
|
117
118
|
with Horizontal():
|
|
118
119
|
with Vertical():
|
|
119
|
-
yield self.card.ui[
|
|
120
|
+
yield self.card.ui["delete"]
|
|
120
121
|
yield Static(classes="button-separator")
|
|
121
|
-
yield self.card.ui[
|
|
122
|
-
yield self.card.ui[
|
|
122
|
+
yield self.card.ui["clone"]
|
|
123
|
+
yield self.card.ui["migration"]
|
|
123
124
|
with Vertical():
|
|
124
|
-
yield self.card.ui[
|
|
125
|
+
yield self.card.ui["xml"]
|
|
125
126
|
yield Static(classes="button-separator")
|
|
126
|
-
yield self.card.ui[
|
|
127
|
+
yield self.card.ui["rename-button"]
|
|
127
128
|
|
|
128
129
|
|
|
129
130
|
class VMCard(Static):
|
|
@@ -228,7 +229,7 @@ class VMCard(Static):
|
|
|
228
229
|
self.webc_status_indicator = new_indicator
|
|
229
230
|
|
|
230
231
|
# Update button label and style
|
|
231
|
-
web_console_button = self.ui.get(
|
|
232
|
+
web_console_button = self.ui.get("web_console")
|
|
232
233
|
if web_console_button:
|
|
233
234
|
if webc_is_running:
|
|
234
235
|
web_console_button.label = "Show Console"
|
|
@@ -249,7 +250,7 @@ class VMCard(Static):
|
|
|
249
250
|
def compose(self):
|
|
250
251
|
self.ui["checkbox"] = Checkbox("", id="vm-select-checkbox", classes="vm-select-checkbox", value=self.is_selected, tooltip="Select VM")
|
|
251
252
|
self.ui["vmname"] = Static(self._get_vm_display_name(), id="vmname", classes="vmname")
|
|
252
|
-
self.ui["status"] = Static(f"{self.status}{self.webc_status_indicator}", id="status"
|
|
253
|
+
self.ui["status"] = Static(f"{self.status}{self.webc_status_indicator}", id="status")
|
|
253
254
|
|
|
254
255
|
# Create all sparkline components
|
|
255
256
|
self.ui["cpu_label"] = Static("", classes="sparkline-label")
|
|
@@ -864,8 +865,7 @@ class VMCard(Static):
|
|
|
864
865
|
self._update_fast_buttons()
|
|
865
866
|
self._update_webc_status()
|
|
866
867
|
|
|
867
|
-
|
|
868
|
-
if self.ui.get(ButtonIds.RENAME_BUTTON):
|
|
868
|
+
if self.ui.get("rename-button"):
|
|
869
869
|
# Check if collapsible is expanded before fetching heavy data
|
|
870
870
|
collapsible = self.ui.get("collapsible")
|
|
871
871
|
if collapsible and not collapsible.collapsed:
|
|
@@ -885,31 +885,31 @@ class VMCard(Static):
|
|
|
885
885
|
is_pmsuspended = self.status == StatusText.PMSUSPENDED
|
|
886
886
|
is_blocked = self.status == StatusText.BLOCKED
|
|
887
887
|
|
|
888
|
-
if not self.ui.get(
|
|
888
|
+
if not self.ui.get("rename-button"):
|
|
889
889
|
return
|
|
890
890
|
|
|
891
|
-
self.ui[
|
|
892
|
-
self.ui[
|
|
893
|
-
self.ui[
|
|
894
|
-
self.ui[
|
|
895
|
-
self.ui[
|
|
896
|
-
self.ui[
|
|
897
|
-
self.ui[
|
|
898
|
-
self.ui[
|
|
899
|
-
self.ui[
|
|
900
|
-
self.ui[
|
|
901
|
-
self.ui[
|
|
902
|
-
self.ui[
|
|
903
|
-
self.ui[
|
|
904
|
-
self.ui[
|
|
905
|
-
self.ui[
|
|
906
|
-
|
|
907
|
-
xml_button = self.ui[
|
|
891
|
+
self.ui["start"].display = is_stopped
|
|
892
|
+
self.ui["shutdown"].display = is_running or is_blocked
|
|
893
|
+
self.ui["stop"].display = is_running or is_paused or is_pmsuspended or is_blocked
|
|
894
|
+
self.ui["delete"].display = is_running or is_paused or is_stopped or is_pmsuspended or is_blocked
|
|
895
|
+
self.ui["clone"].display = is_stopped
|
|
896
|
+
self.ui["migration"].display = not is_loading
|
|
897
|
+
self.ui["rename-button"].display = is_stopped
|
|
898
|
+
self.ui["pause"].display = is_running
|
|
899
|
+
self.ui["resume"].display = is_paused or is_pmsuspended
|
|
900
|
+
self.ui["connect"].display = self.app.r_viewer_available
|
|
901
|
+
self.ui["web_console"].display = (is_running or is_paused or is_blocked)
|
|
902
|
+
self.ui["configure-button"].display = not is_loading
|
|
903
|
+
self.ui["snap_overlay_help"].display = not is_loading
|
|
904
|
+
self.ui["snapshot_take"].display = not is_loading #is_running or is_paused
|
|
905
|
+
self.ui["snapshot_restore"].display = not is_running and not is_loading and not is_blocked
|
|
906
|
+
|
|
907
|
+
xml_button = self.ui["xml"]
|
|
908
908
|
if is_stopped:
|
|
909
|
-
xml_button.label =
|
|
909
|
+
xml_button.label = ButtonLabels.EDIT_XML
|
|
910
910
|
self.stats_view_mode = "resources"
|
|
911
911
|
else:
|
|
912
|
-
xml_button.label =
|
|
912
|
+
xml_button.label = ButtonLabels.VIEW_XML
|
|
913
913
|
xml_button.display = not is_loading
|
|
914
914
|
|
|
915
915
|
def _fetch_actions_state_worker(self):
|
|
@@ -1004,7 +1004,7 @@ class VMCard(Static):
|
|
|
1004
1004
|
|
|
1005
1005
|
def _update_slow_buttons(self, snapshot_summary: dict, has_overlay: bool):
|
|
1006
1006
|
"""Updates buttons that rely on heavy state."""
|
|
1007
|
-
if not self.ui.get(
|
|
1007
|
+
if not self.ui.get("rename-button"):
|
|
1008
1008
|
return
|
|
1009
1009
|
|
|
1010
1010
|
snapshot_count = snapshot_summary.get('count', 0)
|
|
@@ -1031,12 +1031,12 @@ class VMCard(Static):
|
|
|
1031
1031
|
|
|
1032
1032
|
has_snapshots = snapshot_count > 0
|
|
1033
1033
|
|
|
1034
|
-
self.ui[
|
|
1035
|
-
self.ui[
|
|
1034
|
+
self.ui["snapshot_restore"].display = has_snapshots and not is_running and not is_loading and not is_blocked
|
|
1035
|
+
self.ui["snapshot_delete"].display = has_snapshots
|
|
1036
1036
|
|
|
1037
|
-
self.ui[
|
|
1038
|
-
self.ui[
|
|
1039
|
-
self.ui[
|
|
1037
|
+
self.ui["commit_disk"].display = (is_running or is_blocked) and has_overlay
|
|
1038
|
+
self.ui["discard_overlay"].display = is_stopped and has_overlay
|
|
1039
|
+
self.ui["create_overlay"].display = is_stopped and not has_overlay
|
|
1040
1040
|
|
|
1041
1041
|
self.update_snapshot_tab_title(snapshot_count)
|
|
1042
1042
|
|
|
@@ -1046,39 +1046,43 @@ class VMCard(Static):
|
|
|
1046
1046
|
status_widget.remove_class("stopped", "running", "paused", "loading", "pmsuspended", "blocked")
|
|
1047
1047
|
if self.status == StatusText.LOADING:
|
|
1048
1048
|
status_widget.add_class("loading")
|
|
1049
|
+
elif self.status == StatusText.RUNNING:
|
|
1050
|
+
status_widget.add_class("running")
|
|
1051
|
+
elif self.status == StatusText.STOPPED:
|
|
1052
|
+
status_widget.add_class("stopped")
|
|
1053
|
+
elif self.status == StatusText.PAUSED:
|
|
1054
|
+
status_widget.add_class("paused")
|
|
1049
1055
|
elif self.status == StatusText.PMSUSPENDED:
|
|
1050
1056
|
status_widget.add_class("pmsuspended")
|
|
1051
1057
|
elif self.status == StatusText.BLOCKED:
|
|
1052
1058
|
status_widget.add_class("blocked")
|
|
1053
|
-
else:
|
|
1054
|
-
status_widget.add_class(self.status.lower())
|
|
1055
1059
|
|
|
1056
1060
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
1057
1061
|
"""Handle button presses."""
|
|
1058
|
-
if event.button.id ==
|
|
1062
|
+
if event.button.id == "start":
|
|
1059
1063
|
self.post_message(VmActionRequest(self.internal_id, VmAction.START))
|
|
1060
1064
|
return
|
|
1061
1065
|
|
|
1062
1066
|
button_handlers = {
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1067
|
+
"shutdown": self._handle_shutdown_button,
|
|
1068
|
+
"stop": self._handle_stop_button,
|
|
1069
|
+
"pause": self._handle_pause_button,
|
|
1070
|
+
"resume": self._handle_resume_button,
|
|
1071
|
+
"xml": self._handle_xml_button,
|
|
1072
|
+
"connect": self._handle_connect_button,
|
|
1073
|
+
"web_console": self._handle_web_console_button,
|
|
1074
|
+
"snapshot_take": self._handle_snapshot_take_button,
|
|
1075
|
+
"snapshot_restore": self._handle_snapshot_restore_button,
|
|
1076
|
+
"snapshot_delete": self._handle_snapshot_delete_button,
|
|
1077
|
+
"delete": self._handle_delete_button,
|
|
1078
|
+
"clone": self._handle_clone_button,
|
|
1079
|
+
"migration": self._handle_migration_button,
|
|
1080
|
+
"rename-button": self._handle_rename_button,
|
|
1081
|
+
"configure-button": self._handle_configure_button,
|
|
1082
|
+
"create_overlay": self._handle_create_overlay,
|
|
1083
|
+
"commit_disk": self._handle_commit_disk,
|
|
1084
|
+
"discard_overlay": self._handle_discard_overlay,
|
|
1085
|
+
"snap_overlay_help": self._handle_overlay_help,
|
|
1082
1086
|
}
|
|
1083
1087
|
handler = button_handlers.get(event.button.id)
|
|
1084
1088
|
if handler:
|
|
@@ -1100,7 +1104,7 @@ class VMCard(Static):
|
|
|
1100
1104
|
valid_disks = [d['path'] for d in disks if d.get('device_type') == 'disk']
|
|
1101
1105
|
|
|
1102
1106
|
if not valid_disks:
|
|
1103
|
-
self.app.show_error_message(
|
|
1107
|
+
self.app.show_error_message(ErrorMessages.NO_SUITABLE_DISKS_FOR_OVERLAY)
|
|
1104
1108
|
return
|
|
1105
1109
|
|
|
1106
1110
|
target_disk = valid_disks[0]
|
|
@@ -1120,29 +1124,29 @@ class VMCard(Static):
|
|
|
1120
1124
|
return
|
|
1121
1125
|
|
|
1122
1126
|
if was_modified:
|
|
1123
|
-
self.app.show_success_message(
|
|
1127
|
+
self.app.show_success_message(SuccessMessages.INPUT_SANITIZED.format(original_input=overlay_name_raw, sanitized_input=overlay_name))
|
|
1124
1128
|
|
|
1125
1129
|
if not overlay_name:
|
|
1126
|
-
self.app.show_error_message(
|
|
1130
|
+
self.app.show_error_message(ErrorMessages.OVERLAY_NAME_EMPTY_AFTER_SANITIZATION)
|
|
1127
1131
|
return
|
|
1128
1132
|
|
|
1129
1133
|
self.app.vm_service.suppress_vm_events(self.internal_id)
|
|
1130
1134
|
try:
|
|
1131
1135
|
create_external_overlay(self.vm, target_disk, overlay_name)
|
|
1132
|
-
self.app.show_success_message(
|
|
1136
|
+
self.app.show_success_message(SuccessMessages.OVERLAY_CREATED.format(overlay_name=overlay_name))
|
|
1133
1137
|
self.app.vm_service.invalidate_vm_state_cache(self.internal_id)
|
|
1134
1138
|
self._boot_device_checked = False
|
|
1135
1139
|
self.post_message(VmCardUpdateRequest(self.internal_id))
|
|
1136
1140
|
self.update_button_layout()
|
|
1137
1141
|
except Exception as e:
|
|
1138
|
-
self.app.show_error_message(
|
|
1142
|
+
self.app.show_error_message(ErrorMessages.ERROR_CREATING_OVERLAY_TEMPLATE.format(error=e))
|
|
1139
1143
|
finally:
|
|
1140
1144
|
self.app.vm_service.unsuppress_vm_events(self.internal_id)
|
|
1141
1145
|
|
|
1142
1146
|
self.app.push_screen(InputModal("Enter name for new overlay volume:", default_name, restrict=r"[a-zA-Z0-9_-]*"), on_name_input)
|
|
1143
1147
|
|
|
1144
1148
|
except Exception as e:
|
|
1145
|
-
self.app.show_error_message(
|
|
1149
|
+
self.app.show_error_message(ErrorMessages.ERROR_PREPARING_OVERLAY_CREATION_TEMPLATE.format(error=e))
|
|
1146
1150
|
|
|
1147
1151
|
def _handle_discard_overlay(self, event: Button.Pressed) -> None:
|
|
1148
1152
|
"""Handles the discard overlay button press."""
|
|
@@ -1150,7 +1154,7 @@ class VMCard(Static):
|
|
|
1150
1154
|
overlay_disks = get_overlay_disks(self.vm)
|
|
1151
1155
|
|
|
1152
1156
|
if not overlay_disks:
|
|
1153
|
-
self.app.show_error_message(
|
|
1157
|
+
self.app.show_error_message(ErrorMessages.NO_OVERLAY_DISKS_FOUND)
|
|
1154
1158
|
return
|
|
1155
1159
|
|
|
1156
1160
|
def proceed_with_discard(target_disk: str | None):
|
|
@@ -1162,13 +1166,13 @@ class VMCard(Static):
|
|
|
1162
1166
|
self.app.vm_service.suppress_vm_events(self.internal_id)
|
|
1163
1167
|
try:
|
|
1164
1168
|
discard_overlay(self.vm, target_disk)
|
|
1165
|
-
self.app.show_success_message(
|
|
1169
|
+
self.app.show_success_message(SuccessMessages.OVERLAY_DISCARDED.format(target_disk=target_disk))
|
|
1166
1170
|
self.app.vm_service.invalidate_vm_state_cache(self.internal_id)
|
|
1167
1171
|
self._boot_device_checked = False
|
|
1168
1172
|
self.post_message(VmCardUpdateRequest(self.internal_id))
|
|
1169
1173
|
self.update_button_layout()
|
|
1170
1174
|
except Exception as e:
|
|
1171
|
-
self.app.show_error_message(
|
|
1175
|
+
self.app.show_error_message(ErrorMessages.ERROR_DISCARDING_OVERLAY_TEMPLATE.format(error=e))
|
|
1172
1176
|
finally:
|
|
1173
1177
|
self.app.vm_service.unsuppress_vm_events(self.internal_id)
|
|
1174
1178
|
|
|
@@ -1186,7 +1190,7 @@ class VMCard(Static):
|
|
|
1186
1190
|
)
|
|
1187
1191
|
|
|
1188
1192
|
except Exception as e:
|
|
1189
|
-
self.app.show_error_message(
|
|
1193
|
+
self.app.show_error_message(ErrorMessages.ERROR_PREPARING_DISCARD_OVERLAY_TEMPLATE.format(error=e))
|
|
1190
1194
|
|
|
1191
1195
|
|
|
1192
1196
|
def _handle_commit_disk(self, event: Button.Pressed) -> None:
|
|
@@ -1202,7 +1206,7 @@ class VMCard(Static):
|
|
|
1202
1206
|
break
|
|
1203
1207
|
|
|
1204
1208
|
if not target_disk:
|
|
1205
|
-
self.app.show_error_message(
|
|
1209
|
+
self.app.show_error_message(ErrorMessages.NO_DISKS_FOUND_TO_COMMIT)
|
|
1206
1210
|
return
|
|
1207
1211
|
|
|
1208
1212
|
def on_confirm(confirmed: bool):
|
|
@@ -1214,11 +1218,11 @@ class VMCard(Static):
|
|
|
1214
1218
|
self.app.vm_service.suppress_vm_events(self.internal_id)
|
|
1215
1219
|
try:
|
|
1216
1220
|
commit_disk_changes(self.vm, target_disk)
|
|
1217
|
-
self.app.call_from_thread(self.app.show_success_message,
|
|
1221
|
+
self.app.call_from_thread(self.app.show_success_message, SuccessMessages.DISK_COMMITTED)
|
|
1218
1222
|
self.app.call_from_thread(self.app.refresh_vm_list)
|
|
1219
1223
|
self.app.call_from_thread(self.update_button_layout)
|
|
1220
1224
|
except Exception as e:
|
|
1221
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1225
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.ERROR_COMMITTING_DISK_TEMPLATE.format(error=e))
|
|
1222
1226
|
finally:
|
|
1223
1227
|
self.app.vm_service.unsuppress_vm_events(self.internal_id)
|
|
1224
1228
|
self.app.call_from_thread(progress_modal.dismiss)
|
|
@@ -1231,7 +1235,7 @@ class VMCard(Static):
|
|
|
1231
1235
|
)
|
|
1232
1236
|
|
|
1233
1237
|
except Exception as e:
|
|
1234
|
-
self.app.show_error_message(
|
|
1238
|
+
self.app.show_error_message(ErrorMessages.ERROR_PREPARING_COMMIT_TEMPLATE.format(error=e))
|
|
1235
1239
|
|
|
1236
1240
|
def _handle_shutdown_button(self, event: Button.Pressed) -> None:
|
|
1237
1241
|
"""Handles the shutdown button press."""
|
|
@@ -1273,7 +1277,7 @@ class VMCard(Static):
|
|
|
1273
1277
|
self.stop_background_activities()
|
|
1274
1278
|
self.post_message(VmActionRequest(self.internal_id, VmAction.PAUSE))
|
|
1275
1279
|
else:
|
|
1276
|
-
self.app.show_warning_message(
|
|
1280
|
+
self.app.show_warning_message(WarningMessages.LIBVIRT_XML_NO_EFFECTIVE_CHANGE.format(vm_name=self.name))
|
|
1277
1281
|
|
|
1278
1282
|
def _handle_resume_button(self, event: Button.Pressed) -> None:
|
|
1279
1283
|
"""Handles the resume button press."""
|
|
@@ -1304,42 +1308,41 @@ class VMCard(Static):
|
|
|
1304
1308
|
try:
|
|
1305
1309
|
conn = self.vm.connect()
|
|
1306
1310
|
new_domain = conn.defineXML(modified_xml)
|
|
1307
|
-
|
|
1311
|
+
|
|
1308
1312
|
# Verify if changes were effectively applied
|
|
1309
1313
|
new_xml = new_domain.XMLDesc(xml_flags)
|
|
1310
|
-
|
|
1314
|
+
|
|
1311
1315
|
if original_xml == new_xml:
|
|
1312
|
-
self.app.show_warning_message(
|
|
1316
|
+
self.app.show_warning_message(WarningMessages.LIBVIRT_XML_NO_EFFECTIVE_CHANGE.format(vm_name=self.name))
|
|
1313
1317
|
logging.warning(f"XML update for {self.name} resulted in no effective changes.")
|
|
1314
1318
|
else:
|
|
1315
|
-
self.app.show_success_message(
|
|
1319
|
+
self.app.show_success_message(SuccessMessages.VM_CONFIG_UPDATED.format(vm_name=self.name))
|
|
1316
1320
|
logging.info(f"Successfully updated XML for VM: {self.name}")
|
|
1317
|
-
|
|
1321
|
+
|
|
1318
1322
|
self.app.vm_service.invalidate_vm_state_cache(self.internal_id)
|
|
1319
1323
|
self._boot_device_checked = False
|
|
1320
1324
|
self.app.refresh_vm_list()
|
|
1321
1325
|
except libvirt.libvirtError as e:
|
|
1322
|
-
|
|
1323
|
-
self.app.show_error_message(error_msg)
|
|
1326
|
+
self.app.show_error_message(ErrorMessages.INVALID_XML_TEMPLATE.format(vm_name=self.name, error=e))
|
|
1324
1327
|
logging.error(error_msg)
|
|
1325
1328
|
else:
|
|
1326
|
-
self.app.show_success_message(
|
|
1329
|
+
self.app.show_success_message(SuccessMessages.NO_XML_CHANGES)
|
|
1327
1330
|
|
|
1328
1331
|
self.app.push_screen(
|
|
1329
1332
|
XMLDisplayModal(original_xml, read_only=not is_stopped),
|
|
1330
1333
|
handle_xml_modal_result
|
|
1331
1334
|
)
|
|
1332
1335
|
except libvirt.libvirtError as e:
|
|
1333
|
-
self.app.show_error_message(
|
|
1336
|
+
self.app.show_error_message(ErrorMessages.ERROR_GETTING_XML_TEMPLATE.format(vm_name=self.name, error=e))
|
|
1334
1337
|
except Exception as e:
|
|
1335
|
-
self.app.show_error_message(
|
|
1338
|
+
self.app.show_error_message(ErrorMessages.UNEXPECTED_ERROR_OCCURRED_TEMPLATE.format(error=e))
|
|
1336
1339
|
logging.error(f"Unexpected error handling XML button: {traceback.format_exc()}")
|
|
1337
1340
|
|
|
1338
1341
|
def _handle_connect_button(self, event: Button.Pressed) -> None:
|
|
1339
1342
|
"""Handles the connect button press by running the remove virt viewer in a worker."""
|
|
1340
1343
|
logging.info(f"Attempting to connect to VM: {self.name}")
|
|
1341
1344
|
if not hasattr(self, 'conn') or not self.conn:
|
|
1342
|
-
self.app.show_error_message(
|
|
1345
|
+
self.app.show_error_message(ErrorMessages.CONNECTION_INFO_NOT_AVAILABLE)
|
|
1343
1346
|
return
|
|
1344
1347
|
|
|
1345
1348
|
def do_connect() -> None:
|
|
@@ -1368,7 +1371,7 @@ class VMCard(Static):
|
|
|
1368
1371
|
logging.error(f"Failed to spawn {self.app.r_viewer} for {domain_name}: {e}")
|
|
1369
1372
|
self.app.call_from_thread(
|
|
1370
1373
|
self.app.show_error_message,
|
|
1371
|
-
|
|
1374
|
+
ErrorMessages.REMOTE_VIEWER_FAILED_TO_START_TEMPLATE.format(viewer=self.app.r_viewer, domain_name=domain_name, error=e)
|
|
1372
1375
|
)
|
|
1373
1376
|
return
|
|
1374
1377
|
|
|
@@ -1380,13 +1383,13 @@ class VMCard(Static):
|
|
|
1380
1383
|
except libvirt.libvirtError as e:
|
|
1381
1384
|
self.app.call_from_thread(
|
|
1382
1385
|
self.app.show_error_message,
|
|
1383
|
-
|
|
1386
|
+
ErrorMessages.ERROR_GETTING_VM_DETAILS_TEMPLATE.format(vm_name=self.name, error=e)
|
|
1384
1387
|
)
|
|
1385
1388
|
except Exception as e:
|
|
1386
1389
|
logging.error(f"An unexpected error occurred during connect: {e}", exc_info=True)
|
|
1387
1390
|
self.app.call_from_thread(
|
|
1388
1391
|
self.app.show_error_message,
|
|
1389
|
-
|
|
1392
|
+
ErrorMessages.UNEXPECTED_ERROR_CONNECTING
|
|
1390
1393
|
)
|
|
1391
1394
|
|
|
1392
1395
|
self.app.worker_manager.run(do_connect, name=f"r_viewer_{self.name}")
|
|
@@ -1403,7 +1406,7 @@ class VMCard(Static):
|
|
|
1403
1406
|
)
|
|
1404
1407
|
return
|
|
1405
1408
|
except Exception as e:
|
|
1406
|
-
self.app.show_error_message(
|
|
1409
|
+
self.app.show_error_message(ErrorMessages.ERROR_CHECKING_WEB_CONSOLE_STATUS_TEMPLATE.format(vm_name=self.name, error=e))
|
|
1407
1410
|
return
|
|
1408
1411
|
|
|
1409
1412
|
#is_remote = self.app.webconsole_manager.is_remote_connection(self.conn.getURI())
|
|
@@ -1468,9 +1471,9 @@ class VMCard(Static):
|
|
|
1468
1471
|
def finalize_snapshot():
|
|
1469
1472
|
loading_modal.dismiss()
|
|
1470
1473
|
if error:
|
|
1471
|
-
self.app.show_error_message(
|
|
1474
|
+
self.app.show_error_message(ErrorMessages.SNAPSHOT_ERROR_TEMPLATE.format(vm_name=vm_name, error=error))
|
|
1472
1475
|
else:
|
|
1473
|
-
self.app.show_success_message(
|
|
1476
|
+
self.app.show_success_message(SuccessMessages.SNAPSHOT_CREATED.format(snapshot_name=name))
|
|
1474
1477
|
# Defer refresh and restart stats to avoid racing
|
|
1475
1478
|
self.app.set_timer(0.5, self._refresh_snapshot_tab_async)
|
|
1476
1479
|
# Restart stats timer after a delay
|
|
@@ -1498,7 +1501,7 @@ class VMCard(Static):
|
|
|
1498
1501
|
self.app.call_from_thread(loading_modal.dismiss)
|
|
1499
1502
|
|
|
1500
1503
|
if not snapshots_info:
|
|
1501
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1504
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.NO_SNAPSHOTS_TO_RESTORE)
|
|
1502
1505
|
return
|
|
1503
1506
|
|
|
1504
1507
|
def restore_snapshot_callback(snapshot_name: str | None) -> None:
|
|
@@ -1537,10 +1540,10 @@ class VMCard(Static):
|
|
|
1537
1540
|
def finalize_ui():
|
|
1538
1541
|
restore_loading_modal.dismiss()
|
|
1539
1542
|
if error:
|
|
1540
|
-
self.app.show_error_message(
|
|
1543
|
+
self.app.show_error_message(ErrorMessages.ERROR_ON_VM_DURING_ACTION.format(vm_name=vm_name, action='snapshot restore', error=error))
|
|
1541
1544
|
else:
|
|
1542
1545
|
self._boot_device_checked = False
|
|
1543
|
-
self.app.show_success_message(
|
|
1546
|
+
self.app.show_success_message(SuccessMessages.SNAPSHOT_RESTORED.format(snapshot_name=snapshot_name))
|
|
1544
1547
|
logging.info(f"Successfully restored snapshot [b]{snapshot_name}[/b] for VM: {vm_name}")
|
|
1545
1548
|
self.app.refresh_vm_list(force=True)
|
|
1546
1549
|
self.app.call_from_thread(finalize_ui)
|
|
@@ -1550,11 +1553,11 @@ class VMCard(Static):
|
|
|
1550
1553
|
self.app.push_screen,
|
|
1551
1554
|
SelectSnapshotDialog(snapshots_info, "Select snapshot to restore"),
|
|
1552
1555
|
restore_snapshot_callback
|
|
1553
|
-
|
|
1556
|
+
)
|
|
1554
1557
|
|
|
1555
1558
|
except Exception as e:
|
|
1556
1559
|
self.app.call_from_thread(loading_modal.dismiss)
|
|
1557
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1560
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.ERROR_FETCHING_SNAPSHOTS_TEMPLATE.format(error=e))
|
|
1558
1561
|
|
|
1559
1562
|
self.app.worker_manager.run(fetch_and_show_worker, name=f"snapshot_restore_fetch_{self.internal_id}")
|
|
1560
1563
|
|
|
@@ -1575,7 +1578,7 @@ class VMCard(Static):
|
|
|
1575
1578
|
self.app.call_from_thread(loading_modal.dismiss)
|
|
1576
1579
|
|
|
1577
1580
|
if not snapshots_info:
|
|
1578
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1581
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.NO_SNAPSHOTS_TO_DELETE)
|
|
1579
1582
|
return
|
|
1580
1583
|
|
|
1581
1584
|
def delete_snapshot_callback(snapshot_name: str | None) -> None:
|
|
@@ -1607,9 +1610,9 @@ class VMCard(Static):
|
|
|
1607
1610
|
def finalize_ui():
|
|
1608
1611
|
loading_modal.dismiss()
|
|
1609
1612
|
if error:
|
|
1610
|
-
self.app.show_error_message(
|
|
1613
|
+
self.app.show_error_message(ErrorMessages.ERROR_ON_VM_DURING_ACTION.format(vm_name=vm_name, action='snapshot delete', error=error))
|
|
1611
1614
|
else:
|
|
1612
|
-
self.app.show_success_message(
|
|
1615
|
+
self.app.show_success_message(SuccessMessages.SNAPSHOT_DELETED.format(snapshot_name=snapshot_name))
|
|
1613
1616
|
logging.info(f"Successfully deleted snapshot '{snapshot_name}' for VM: {vm_name}")
|
|
1614
1617
|
self.app.set_timer(0.1, self._refresh_snapshot_tab_async)
|
|
1615
1618
|
# Restart stats timer
|
|
@@ -1631,7 +1634,7 @@ class VMCard(Static):
|
|
|
1631
1634
|
|
|
1632
1635
|
except Exception as e:
|
|
1633
1636
|
self.app.call_from_thread(loading_modal.dismiss)
|
|
1634
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1637
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.ERROR_FETCHING_SNAPSHOTS_TEMPLATE.format(error=e))
|
|
1635
1638
|
|
|
1636
1639
|
self.app.worker_manager.run(fetch_and_show_worker, name=f"snapshot_delete_fetch_{self.internal_id}")
|
|
1637
1640
|
|
|
@@ -1685,12 +1688,12 @@ class VMCard(Static):
|
|
|
1685
1688
|
pass
|
|
1686
1689
|
|
|
1687
1690
|
# Also update button visibility
|
|
1688
|
-
if self.ui.get(
|
|
1691
|
+
if self.ui.get("rename-button"):
|
|
1689
1692
|
has_snapshots = snapshot_count > 0
|
|
1690
1693
|
is_running = self.status == StatusText.RUNNING
|
|
1691
1694
|
is_loading = self.status == StatusText.LOADING
|
|
1692
|
-
self.ui[
|
|
1693
|
-
self.ui[
|
|
1695
|
+
self.ui["snapshot_restore"].display = has_snapshots and not is_running and not is_loading
|
|
1696
|
+
self.ui["snapshot_delete"].display = has_snapshots
|
|
1694
1697
|
|
|
1695
1698
|
self.app.call_from_thread(update_ui)
|
|
1696
1699
|
|
|
@@ -1744,7 +1747,7 @@ class VMCard(Static):
|
|
|
1744
1747
|
# delete_vm handles opening its own connection
|
|
1745
1748
|
delete_vm(self.vm, delete_storage=delete_storage, delete_nvram=True, log_callback=log_callback)
|
|
1746
1749
|
|
|
1747
|
-
self.app.call_from_thread(self.app.show_success_message,
|
|
1750
|
+
self.app.call_from_thread(self.app.show_success_message, SuccessMessages.VM_DELETED.format(vm_name=vm_name))
|
|
1748
1751
|
|
|
1749
1752
|
# Invalidate cache
|
|
1750
1753
|
self.app.vm_service.invalidate_vm_cache(internal_id)
|
|
@@ -1757,7 +1760,7 @@ class VMCard(Static):
|
|
|
1757
1760
|
|
|
1758
1761
|
except Exception as e:
|
|
1759
1762
|
self.app.vm_service.unsuppress_vm_events(internal_id)
|
|
1760
|
-
self.app.call_from_thread(self.app.show_error_message,
|
|
1763
|
+
self.app.call_from_thread(self.app.show_error_message, ErrorMessages.ERROR_DELETING_VM_TEMPLATE.format(vm_name=vm_name, error=e))
|
|
1761
1764
|
finally:
|
|
1762
1765
|
self.app.call_from_thread(progress_modal.dismiss)
|
|
1763
1766
|
|
|
@@ -1812,8 +1815,8 @@ class VMCard(Static):
|
|
|
1812
1815
|
existing_vm_names.add(name)
|
|
1813
1816
|
|
|
1814
1817
|
except libvirt.libvirtError as e:
|
|
1815
|
-
log_callback(f"ERROR:
|
|
1816
|
-
app.call_from_thread(app.show_error_message,
|
|
1818
|
+
log_callback(f"ERROR: {ErrorMessages.ERROR_GETTING_EXISTING_VM_NAMES_TEMPLATE.format(error=e)}")
|
|
1819
|
+
app.call_from_thread(app.show_error_message, ErrorMessages.ERROR_GETTING_EXISTING_VM_NAMES_TEMPLATE.format(error=e))
|
|
1817
1820
|
app.call_from_thread(progress_modal.dismiss)
|
|
1818
1821
|
return
|
|
1819
1822
|
|
|
@@ -1852,11 +1855,11 @@ class VMCard(Static):
|
|
|
1852
1855
|
app.call_from_thread(lambda: progress_modal.query_one("#progress-bar").advance(1))
|
|
1853
1856
|
|
|
1854
1857
|
if success_clones:
|
|
1855
|
-
msg =
|
|
1858
|
+
msg = SuccessMessages.VM_CLONED.format(vm_names=', '.join(success_clones))
|
|
1856
1859
|
app.call_from_thread(app.show_success_message, msg)
|
|
1857
1860
|
log_callback(msg)
|
|
1858
1861
|
if failed_clones:
|
|
1859
|
-
msg =
|
|
1862
|
+
msg = ErrorMessages.VM_CLONE_FAILED_TEMPLATE.format(vm_names=', '.join(failed_clones))
|
|
1860
1863
|
app.call_from_thread(app.show_error_message, msg)
|
|
1861
1864
|
log_callback(f"ERROR: {msg}")
|
|
1862
1865
|
|
|
@@ -1895,13 +1898,13 @@ class VMCard(Static):
|
|
|
1895
1898
|
return
|
|
1896
1899
|
|
|
1897
1900
|
if was_modified:
|
|
1898
|
-
self.app.show_success_message(
|
|
1901
|
+
self.app.show_success_message(SuccessMessages.INPUT_SANITIZED.format(original_input=new_name_raw, sanitized_input=new_name))
|
|
1899
1902
|
|
|
1900
1903
|
if not new_name:
|
|
1901
|
-
self.app.show_error_message(
|
|
1904
|
+
self.app.show_error_message(ErrorMessages.VM_NAME_EMPTY_AFTER_SANITIZATION)
|
|
1902
1905
|
return
|
|
1903
1906
|
if new_name == self.name:
|
|
1904
|
-
self.app.show_success_message(
|
|
1907
|
+
self.app.show_success_message(SuccessMessages.VM_RENAME_NO_CHANGE)
|
|
1905
1908
|
return
|
|
1906
1909
|
|
|
1907
1910
|
def do_rename():
|
|
@@ -1909,14 +1912,13 @@ class VMCard(Static):
|
|
|
1909
1912
|
self.app.vm_service.suppress_vm_events(internal_id)
|
|
1910
1913
|
try:
|
|
1911
1914
|
rename_vm(self.vm, new_name)
|
|
1912
|
-
|
|
1913
|
-
self.app.show_success_message(msg)
|
|
1915
|
+
self.app.show_success_message(SuccessMessages.VM_RENAMED.format(old_name=self.name, new_name=new_name))
|
|
1914
1916
|
self.app.vm_service.invalidate_domain_cache()
|
|
1915
1917
|
self._boot_device_checked = False
|
|
1916
1918
|
self.app.refresh_vm_list()
|
|
1917
1919
|
logging.info(f"Successfully renamed VM '{self.name}' to '{new_name}'")
|
|
1918
1920
|
except Exception as e:
|
|
1919
|
-
self.app.show_error_message(
|
|
1921
|
+
self.app.show_error_message(ErrorMessages.ERROR_RENAMING_VM_TEMPLATE.format(vm_name=self.name, error=e))
|
|
1920
1922
|
finally:
|
|
1921
1923
|
self.app.vm_service.unsuppress_vm_events(internal_id)
|
|
1922
1924
|
|
|
@@ -1928,7 +1930,7 @@ class VMCard(Static):
|
|
|
1928
1930
|
if delete_snapshots:
|
|
1929
1931
|
self.app.set_timer(0.1, self._refresh_snapshot_tab_async)
|
|
1930
1932
|
else:
|
|
1931
|
-
self.app.show_success_message(
|
|
1933
|
+
self.app.show_success_message(SuccessMessages.VM_RENAME_CANCELLED)
|
|
1932
1934
|
|
|
1933
1935
|
msg = f"Are you sure you want to rename VM {self.name} to {new_name}?\n\nWarning: This operation involves undefining and redefining the VM."
|
|
1934
1936
|
self.app.push_screen(
|
|
@@ -1968,7 +1970,7 @@ class VMCard(Static):
|
|
|
1968
1970
|
def show_details():
|
|
1969
1971
|
loading_modal.dismiss()
|
|
1970
1972
|
if not result:
|
|
1971
|
-
self.app.show_error_message(
|
|
1973
|
+
self.app.show_error_message(ErrorMessages.VM_NOT_FOUND_ON_ACTIVE_SERVER_TEMPLATE.format(vm_name=vm_name, uuid=uuid))
|
|
1972
1974
|
return
|
|
1973
1975
|
|
|
1974
1976
|
vm_info, domain, conn_for_domain = result
|
|
@@ -1987,18 +1989,18 @@ class VMCard(Static):
|
|
|
1987
1989
|
except Exception as e:
|
|
1988
1990
|
def show_error():
|
|
1989
1991
|
loading_modal.dismiss()
|
|
1990
|
-
self.app.show_error_message(
|
|
1992
|
+
self.app.show_error_message(ErrorMessages.ERROR_GETTING_VM_DETAILS_TEMPLATE.format(vm_name=vm_name, error=e))
|
|
1991
1993
|
self.app.call_from_thread(show_error)
|
|
1992
1994
|
|
|
1993
1995
|
self.app.worker_manager.run(get_details_worker, name=f"get_details_{uuid}")
|
|
1994
1996
|
|
|
1995
1997
|
except Exception as e:
|
|
1996
|
-
self.app.show_error_message(
|
|
1998
|
+
self.app.show_error_message(ErrorMessages.ERROR_GETTING_ID_TEMPLATE.format(vm_name=self.name, error=e))
|
|
1997
1999
|
|
|
1998
2000
|
def _handle_migration_button(self, event: Button.Pressed) -> None:
|
|
1999
2001
|
"""Handles the migration button press."""
|
|
2000
2002
|
if len(self.app.active_uris) < 2:
|
|
2001
|
-
self.app.show_error_message(
|
|
2003
|
+
self.app.show_error_message(ErrorMessages.SELECT_AT_LEAST_TWO_SERVERS_FOR_MIGRATION)
|
|
2002
2004
|
return
|
|
2003
2005
|
|
|
2004
2006
|
selected_vm_uuids = self.app.selected_vm_uuids
|
|
@@ -2019,8 +2021,8 @@ class VMCard(Static):
|
|
|
2019
2021
|
found_domain = False
|
|
2020
2022
|
else:
|
|
2021
2023
|
found_domain = False
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
+
if not vm_info:
|
|
2025
|
+
self.app.show_error_message(ErrorMessages.SELECTED_VM_NOT_FOUND_ON_ACTIVE_SERVER_TEMPLATE.format(uuid=uuid))
|
|
2024
2026
|
|
|
2025
2027
|
if not selected_vms:
|
|
2026
2028
|
selected_vms = [self.vm]
|
|
@@ -2037,7 +2039,7 @@ class VMCard(Static):
|
|
|
2037
2039
|
source_conns.add(uri)
|
|
2038
2040
|
|
|
2039
2041
|
if len(source_conns) > 1:
|
|
2040
|
-
self.app.show_error_message(
|
|
2042
|
+
self.app.show_error_message(ErrorMessages.DIFFERENT_SOURCE_HOSTS)
|
|
2041
2043
|
return
|
|
2042
2044
|
|
|
2043
2045
|
#active_vms = [vm for vm in selected_vms if vm.isActive()]
|
|
@@ -2058,7 +2060,7 @@ class VMCard(Static):
|
|
|
2058
2060
|
|
|
2059
2061
|
is_live = len(active_vms) > 0
|
|
2060
2062
|
if is_live and len(active_vms) < len(selected_vms):
|
|
2061
|
-
self.app.show_error_message(
|
|
2063
|
+
self.app.show_error_message(ErrorMessages.MIXED_VM_STATES)
|
|
2062
2064
|
return
|
|
2063
2065
|
|
|
2064
2066
|
active_uris = self.app.vm_service.get_all_uris()
|