feat: implement resource resizing for VMs with storage management

- Added KnownHostsManager to handle cleanup of SSH known_hosts entries upon VM deletion.
- Introduced disk_size_bytes method in ImageStore to read logical disk capacity.
- Enhanced LifecycleService to manage VM resource resizing, including CPU, RAM, and storage.
- Updated application configuration to support known_hosts_files for SSH management.
- Modified dashboard to include resource resizing options in the UI.
- Improved error handling and validation for resource inputs in the dashboard.
- Removed obsolete .pyc files from the repository.
This commit is contained in:
2026-09-21 20:37:52 +05:30
parent fb80ce7c8a
commit 4a46685a4c
40 changed files with 1048 additions and 63 deletions
+14
View File
@@ -40,6 +40,7 @@ class Settings:
api_token: str | None = None
api_tls_cert: Path | None = None
api_tls_key: Path | None = None
known_hosts_files: tuple[Path, ...] | None = None
api_timeout_s: float = 2.0
api_socket_timeout_s: float = 5.0
terminate_timeout_s: float = 5.0
@@ -66,6 +67,8 @@ class Settings:
raise ConfigurationError("gateway must be a usable host address")
if len(self.bridge) > 15:
raise ConfigurationError("bridge name must be 15 characters or fewer")
if self.known_hosts_files is not None and any(not path.is_absolute() for path in self.known_hosts_files):
raise ConfigurationError("UVM_KNOWN_HOSTS_FILES must contain absolute file paths")
if self.api_token is not None:
if not self.api_token or not all(33 <= ord(character) <= 126 for character in self.api_token):
raise ConfigurationError(
@@ -148,6 +151,7 @@ class Settings:
api_token=_optional_environment_value("UVM_API_TOKEN"),
api_tls_cert=_optional_environment_path("UVM_API_TLS_CERT"),
api_tls_key=_optional_environment_path("UVM_API_TLS_KEY"),
known_hosts_files=_known_hosts_environment_paths(),
)
@@ -161,6 +165,16 @@ def _optional_environment_path(name: str) -> Path | None:
return Path(value).expanduser() if value else None
def _known_hosts_environment_paths() -> tuple[Path, ...] | None:
value = _optional_environment_value("UVM_KNOWN_HOSTS_FILES")
if value is None:
return None
parts = value.split(os.pathsep)
if any(not part for part in parts):
raise ConfigurationError("UVM_KNOWN_HOSTS_FILES must be a colon-separated list of file paths")
return tuple(Path(part).expanduser() for part in parts)
def _boolean_environment_value(name: str, *, default: bool) -> bool:
value = os.environ.get(name)
if value is None: