golem-vm-provider 0.1.12__tar.gz → 0.1.13__tar.gz
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.
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/PKG-INFO +1 -1
- golem_vm_provider-0.1.13/provider/config.py +253 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/pyproject.toml +1 -1
- golem_vm_provider-0.1.12/provider/config.py +0 -218
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/README.md +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/__init__.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/api/__init__.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/api/models.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/api/routes.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/discovery/__init__.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/discovery/advertiser.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/discovery/resource_tracker.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/main.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/network/port_verifier.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/security/ethereum.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/utils/ascii_art.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/utils/logging.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/utils/port_display.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/utils/retry.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/__init__.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/cloud_init.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/models.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/multipass.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/name_mapper.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/port_manager.py +0 -0
- {golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/vm/proxy_manager.py +0 -0
@@ -0,0 +1,253 @@
|
|
1
|
+
import os
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Optional
|
4
|
+
import uuid
|
5
|
+
|
6
|
+
from pydantic import BaseSettings, validator, Field
|
7
|
+
from .utils.logging import setup_logger
|
8
|
+
|
9
|
+
logger = setup_logger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class Settings(BaseSettings):
|
13
|
+
"""Provider configuration settings."""
|
14
|
+
|
15
|
+
# API Settings
|
16
|
+
DEBUG: bool = True
|
17
|
+
HOST: str = "0.0.0.0"
|
18
|
+
PORT: int = 7466
|
19
|
+
|
20
|
+
# Provider Settings
|
21
|
+
PROVIDER_ID: str = "" # Will be set from Ethereum identity
|
22
|
+
PROVIDER_NAME: str = "golem-provider"
|
23
|
+
PROVIDER_COUNTRY: str = "SE"
|
24
|
+
ETHEREUM_KEY_DIR: str = ""
|
25
|
+
|
26
|
+
@validator("ETHEREUM_KEY_DIR", pre=True)
|
27
|
+
def resolve_key_dir(cls, v: str) -> str:
|
28
|
+
"""Resolve Ethereum key directory path."""
|
29
|
+
if not v:
|
30
|
+
return str(Path.home() / ".golem" / "provider" / "keys")
|
31
|
+
path = Path(v)
|
32
|
+
if not path.is_absolute():
|
33
|
+
path = Path.home() / path
|
34
|
+
return str(path)
|
35
|
+
|
36
|
+
@validator("PROVIDER_ID", always=True)
|
37
|
+
def get_or_create_provider_id(cls, v: str, values: dict) -> str:
|
38
|
+
"""Get or create provider ID from Ethereum identity."""
|
39
|
+
from provider.security.ethereum import EthereumIdentity
|
40
|
+
|
41
|
+
# If ID provided in env, use it
|
42
|
+
if v:
|
43
|
+
return v
|
44
|
+
|
45
|
+
# Get ID from Ethereum identity
|
46
|
+
key_dir = values.get("ETHEREUM_KEY_DIR")
|
47
|
+
identity = EthereumIdentity(key_dir)
|
48
|
+
return identity.get_or_create_identity()
|
49
|
+
|
50
|
+
# Discovery Service Settings
|
51
|
+
DISCOVERY_URL: str = "http://195.201.39.101:9001"
|
52
|
+
ADVERTISEMENT_INTERVAL: int = 240 # seconds
|
53
|
+
|
54
|
+
# VM Settings
|
55
|
+
MAX_VMS: int = 10
|
56
|
+
DEFAULT_VM_IMAGE: str = "ubuntu:24.04"
|
57
|
+
VM_DATA_DIR: str = ""
|
58
|
+
SSH_KEY_DIR: str = ""
|
59
|
+
|
60
|
+
@validator("VM_DATA_DIR", pre=True)
|
61
|
+
def resolve_vm_data_dir(cls, v: str) -> str:
|
62
|
+
"""Resolve VM data directory path."""
|
63
|
+
if not v:
|
64
|
+
return str(Path.home() / ".golem" / "provider" / "vms")
|
65
|
+
path = Path(v)
|
66
|
+
if not path.is_absolute():
|
67
|
+
path = Path.home() / path
|
68
|
+
return str(path)
|
69
|
+
|
70
|
+
@validator("SSH_KEY_DIR", pre=True)
|
71
|
+
def resolve_ssh_key_dir(cls, v: str) -> str:
|
72
|
+
"""Resolve SSH key directory path."""
|
73
|
+
if not v:
|
74
|
+
return str(Path.home() / ".golem" / "provider" / "ssh")
|
75
|
+
path = Path(v)
|
76
|
+
if not path.is_absolute():
|
77
|
+
path = Path.home() / path
|
78
|
+
return str(path)
|
79
|
+
|
80
|
+
# Resource Settings
|
81
|
+
MIN_MEMORY_GB: int = 1
|
82
|
+
MIN_STORAGE_GB: int = 10
|
83
|
+
MIN_CPU_CORES: int = 1
|
84
|
+
|
85
|
+
# Resource Thresholds (%)
|
86
|
+
CPU_THRESHOLD: int = 90
|
87
|
+
MEMORY_THRESHOLD: int = 85
|
88
|
+
STORAGE_THRESHOLD: int = 90
|
89
|
+
|
90
|
+
# Rate Limiting
|
91
|
+
RATE_LIMIT_PER_MINUTE: int = 100
|
92
|
+
|
93
|
+
# Multipass Settings
|
94
|
+
MULTIPASS_BINARY_PATH: str = Field(
|
95
|
+
default="",
|
96
|
+
description="Path to multipass binary"
|
97
|
+
)
|
98
|
+
|
99
|
+
@validator("MULTIPASS_BINARY_PATH")
|
100
|
+
def detect_multipass_path(cls, v: str) -> str:
|
101
|
+
"""Detect and validate Multipass binary path."""
|
102
|
+
import platform
|
103
|
+
import subprocess
|
104
|
+
|
105
|
+
def validate_path(path: str) -> bool:
|
106
|
+
"""Validate that a path exists and is executable."""
|
107
|
+
return os.path.isfile(path) and os.access(path, os.X_OK)
|
108
|
+
|
109
|
+
# If path provided via environment variable, ONLY validate that path
|
110
|
+
if v:
|
111
|
+
logger.debug(f"Using provided multipass path: {v}")
|
112
|
+
if not validate_path(v):
|
113
|
+
logger.error(f"Provided path {v} is invalid or not executable")
|
114
|
+
raise ValueError(f"Invalid multipass binary path: {v}")
|
115
|
+
return v
|
116
|
+
|
117
|
+
logger.debug("No multipass path provided, attempting auto-detection")
|
118
|
+
system = platform.system().lower()
|
119
|
+
logger.debug(f"Detected OS: {system}")
|
120
|
+
binary_name = "multipass.exe" if system == "windows" else "multipass"
|
121
|
+
|
122
|
+
# Try to find multipass based on OS
|
123
|
+
if system == "linux":
|
124
|
+
logger.debug("Checking for snap installation on Linux")
|
125
|
+
# First try to find snap and check if multipass is installed
|
126
|
+
try:
|
127
|
+
# Check if snap exists
|
128
|
+
snap_result = subprocess.run(
|
129
|
+
["which", "snap"],
|
130
|
+
capture_output=True,
|
131
|
+
text=True,
|
132
|
+
check=True
|
133
|
+
)
|
134
|
+
if snap_result.returncode == 0:
|
135
|
+
logger.debug("Found snap, checking for multipass installation")
|
136
|
+
# Check if multipass is installed via snap
|
137
|
+
try:
|
138
|
+
snap_list = subprocess.run(
|
139
|
+
["snap", "list", "multipass"],
|
140
|
+
capture_output=True,
|
141
|
+
text=True,
|
142
|
+
check=True
|
143
|
+
)
|
144
|
+
if snap_list.returncode == 0:
|
145
|
+
snap_path = "/snap/bin/multipass"
|
146
|
+
if validate_path(snap_path):
|
147
|
+
logger.debug(f"Found multipass via snap at {snap_path}")
|
148
|
+
return snap_path
|
149
|
+
except subprocess.CalledProcessError:
|
150
|
+
logger.debug("Multipass not installed via snap")
|
151
|
+
pass
|
152
|
+
except subprocess.CalledProcessError:
|
153
|
+
logger.debug("Snap not found")
|
154
|
+
pass
|
155
|
+
|
156
|
+
# Common Linux paths if snap installation not found
|
157
|
+
search_paths = [
|
158
|
+
"/usr/local/bin",
|
159
|
+
"/usr/bin",
|
160
|
+
"/snap/bin"
|
161
|
+
]
|
162
|
+
logger.debug(f"Checking common Linux paths: {search_paths}")
|
163
|
+
|
164
|
+
elif system == "darwin": # macOS
|
165
|
+
search_paths = [
|
166
|
+
"/opt/homebrew/bin", # M1 Mac
|
167
|
+
"/usr/local/bin", # Intel Mac
|
168
|
+
"/opt/local/bin" # MacPorts
|
169
|
+
]
|
170
|
+
logger.debug(f"Checking macOS paths: {search_paths}")
|
171
|
+
|
172
|
+
elif system == "windows":
|
173
|
+
search_paths = [
|
174
|
+
os.path.expandvars(r"%ProgramFiles%\Multipass"),
|
175
|
+
os.path.expandvars(r"%ProgramFiles(x86)%\Multipass"),
|
176
|
+
os.path.expandvars(r"%LocalAppData%\Multipass")
|
177
|
+
]
|
178
|
+
logger.debug(f"Checking Windows paths: {search_paths}")
|
179
|
+
|
180
|
+
else:
|
181
|
+
search_paths = ["/usr/local/bin", "/usr/bin"]
|
182
|
+
logger.debug(f"Checking default paths: {search_paths}")
|
183
|
+
|
184
|
+
# Search for multipass binary in OS-specific paths
|
185
|
+
for directory in search_paths:
|
186
|
+
path = os.path.join(directory, binary_name)
|
187
|
+
logger.debug(f"Checking path: {path}")
|
188
|
+
if validate_path(path):
|
189
|
+
logger.debug(f"Found valid multipass binary at: {path}")
|
190
|
+
return path
|
191
|
+
else:
|
192
|
+
logger.debug(f"No valid multipass binary at: {path}")
|
193
|
+
|
194
|
+
# OS-specific installation instructions
|
195
|
+
if system == "linux":
|
196
|
+
raise ValueError(
|
197
|
+
"Multipass binary not found. Please install using:\n"
|
198
|
+
"sudo snap install multipass\n"
|
199
|
+
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
200
|
+
)
|
201
|
+
elif system == "darwin":
|
202
|
+
raise ValueError(
|
203
|
+
"Multipass binary not found. Please install using:\n"
|
204
|
+
"brew install multipass\n"
|
205
|
+
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
206
|
+
)
|
207
|
+
elif system == "windows":
|
208
|
+
raise ValueError(
|
209
|
+
"Multipass binary not found. Please install from:\n"
|
210
|
+
"Microsoft Store or https://multipass.run/download/windows\n"
|
211
|
+
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
212
|
+
)
|
213
|
+
else:
|
214
|
+
raise ValueError(
|
215
|
+
"Multipass binary not found. Please install Multipass or set "
|
216
|
+
"GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
217
|
+
)
|
218
|
+
|
219
|
+
# Proxy Settings
|
220
|
+
PORT_RANGE_START: int = 50800
|
221
|
+
PORT_RANGE_END: int = 50900
|
222
|
+
PROXY_STATE_DIR: str = ""
|
223
|
+
PUBLIC_IP: Optional[str] = None
|
224
|
+
|
225
|
+
@validator("PROXY_STATE_DIR", pre=True)
|
226
|
+
def resolve_proxy_state_dir(cls, v: str) -> str:
|
227
|
+
"""Resolve proxy state directory path."""
|
228
|
+
if not v:
|
229
|
+
return str(Path.home() / ".golem" / "provider" / "proxy")
|
230
|
+
path = Path(v)
|
231
|
+
if not path.is_absolute():
|
232
|
+
path = Path.home() / path
|
233
|
+
return str(path)
|
234
|
+
|
235
|
+
@validator("PUBLIC_IP", pre=True)
|
236
|
+
def get_public_ip(cls, v: Optional[str]) -> Optional[str]:
|
237
|
+
"""Get public IP if set to 'auto'."""
|
238
|
+
if v == "auto":
|
239
|
+
try:
|
240
|
+
import requests
|
241
|
+
response = requests.get("https://api.ipify.org")
|
242
|
+
return response.text.strip()
|
243
|
+
except Exception:
|
244
|
+
return None
|
245
|
+
return v
|
246
|
+
|
247
|
+
class Config:
|
248
|
+
env_prefix = "GOLEM_PROVIDER_"
|
249
|
+
case_sensitive = True
|
250
|
+
|
251
|
+
|
252
|
+
# Global settings instance
|
253
|
+
settings = Settings()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "golem-vm-provider"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.13"
|
4
4
|
description = "VM on Golem Provider Node - Run your own provider node to offer VMs on the Golem Network"
|
5
5
|
authors = ["Phillip Jensen <phillip+vm-on-golem@golemgrid.com>"]
|
6
6
|
readme = "README.md"
|
@@ -1,218 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from pathlib import Path
|
3
|
-
from typing import Optional
|
4
|
-
import uuid
|
5
|
-
|
6
|
-
from pydantic import BaseSettings, validator
|
7
|
-
|
8
|
-
|
9
|
-
class Settings(BaseSettings):
|
10
|
-
"""Provider configuration settings."""
|
11
|
-
|
12
|
-
# API Settings
|
13
|
-
DEBUG: bool = True
|
14
|
-
HOST: str = "0.0.0.0"
|
15
|
-
PORT: int = 7466
|
16
|
-
|
17
|
-
# Provider Settings
|
18
|
-
PROVIDER_ID: str = "" # Will be set from Ethereum identity
|
19
|
-
PROVIDER_NAME: str = "golem-provider"
|
20
|
-
PROVIDER_COUNTRY: str = "SE"
|
21
|
-
ETHEREUM_KEY_DIR: str = ""
|
22
|
-
|
23
|
-
@validator("ETHEREUM_KEY_DIR", pre=True)
|
24
|
-
def resolve_key_dir(cls, v: str) -> str:
|
25
|
-
"""Resolve Ethereum key directory path."""
|
26
|
-
if not v:
|
27
|
-
return str(Path.home() / ".golem" / "provider" / "keys")
|
28
|
-
path = Path(v)
|
29
|
-
if not path.is_absolute():
|
30
|
-
path = Path.home() / path
|
31
|
-
return str(path)
|
32
|
-
|
33
|
-
@validator("PROVIDER_ID", always=True)
|
34
|
-
def get_or_create_provider_id(cls, v: str, values: dict) -> str:
|
35
|
-
"""Get or create provider ID from Ethereum identity."""
|
36
|
-
from provider.security.ethereum import EthereumIdentity
|
37
|
-
|
38
|
-
# If ID provided in env, use it
|
39
|
-
if v:
|
40
|
-
return v
|
41
|
-
|
42
|
-
# Get ID from Ethereum identity
|
43
|
-
key_dir = values.get("ETHEREUM_KEY_DIR")
|
44
|
-
identity = EthereumIdentity(key_dir)
|
45
|
-
return identity.get_or_create_identity()
|
46
|
-
|
47
|
-
# Discovery Service Settings
|
48
|
-
DISCOVERY_URL: str = "http://195.201.39.101:9001"
|
49
|
-
ADVERTISEMENT_INTERVAL: int = 240 # seconds
|
50
|
-
|
51
|
-
# VM Settings
|
52
|
-
MAX_VMS: int = 10
|
53
|
-
DEFAULT_VM_IMAGE: str = "ubuntu:24.04"
|
54
|
-
VM_DATA_DIR: str = ""
|
55
|
-
SSH_KEY_DIR: str = ""
|
56
|
-
|
57
|
-
@validator("VM_DATA_DIR", pre=True)
|
58
|
-
def resolve_vm_data_dir(cls, v: str) -> str:
|
59
|
-
"""Resolve VM data directory path."""
|
60
|
-
if not v:
|
61
|
-
return str(Path.home() / ".golem" / "provider" / "vms")
|
62
|
-
path = Path(v)
|
63
|
-
if not path.is_absolute():
|
64
|
-
path = Path.home() / path
|
65
|
-
return str(path)
|
66
|
-
|
67
|
-
@validator("SSH_KEY_DIR", pre=True)
|
68
|
-
def resolve_ssh_key_dir(cls, v: str) -> str:
|
69
|
-
"""Resolve SSH key directory path."""
|
70
|
-
if not v:
|
71
|
-
return str(Path.home() / ".golem" / "provider" / "ssh")
|
72
|
-
path = Path(v)
|
73
|
-
if not path.is_absolute():
|
74
|
-
path = Path.home() / path
|
75
|
-
return str(path)
|
76
|
-
|
77
|
-
# Resource Settings
|
78
|
-
MIN_MEMORY_GB: int = 1
|
79
|
-
MIN_STORAGE_GB: int = 10
|
80
|
-
MIN_CPU_CORES: int = 1
|
81
|
-
|
82
|
-
# Resource Thresholds (%)
|
83
|
-
CPU_THRESHOLD: int = 90
|
84
|
-
MEMORY_THRESHOLD: int = 85
|
85
|
-
STORAGE_THRESHOLD: int = 90
|
86
|
-
|
87
|
-
# Rate Limiting
|
88
|
-
RATE_LIMIT_PER_MINUTE: int = 100
|
89
|
-
|
90
|
-
# Multipass Settings
|
91
|
-
MULTIPASS_BINARY_PATH: str = ""
|
92
|
-
|
93
|
-
@validator("MULTIPASS_BINARY_PATH", pre=True)
|
94
|
-
def detect_multipass_path(cls, v: str) -> str:
|
95
|
-
"""Detect and validate Multipass binary path."""
|
96
|
-
if v:
|
97
|
-
path = v
|
98
|
-
else:
|
99
|
-
import platform
|
100
|
-
import subprocess
|
101
|
-
|
102
|
-
system = platform.system().lower()
|
103
|
-
binary_name = "multipass.exe" if system == "windows" else "multipass"
|
104
|
-
|
105
|
-
# Try to find multipass based on OS
|
106
|
-
if system == "linux":
|
107
|
-
# First try to find snap
|
108
|
-
try:
|
109
|
-
snap_result = subprocess.run(
|
110
|
-
["which", "snap"],
|
111
|
-
capture_output=True,
|
112
|
-
text=True
|
113
|
-
)
|
114
|
-
if snap_result.returncode == 0:
|
115
|
-
# If snap exists, check if multipass is installed
|
116
|
-
snap_path = "/snap/bin/multipass"
|
117
|
-
if os.path.isfile(snap_path) and os.access(snap_path, os.X_OK):
|
118
|
-
return snap_path
|
119
|
-
except subprocess.SubprocessError:
|
120
|
-
pass
|
121
|
-
|
122
|
-
# Common Linux paths
|
123
|
-
search_paths = [
|
124
|
-
"/usr/local/bin",
|
125
|
-
"/usr/bin",
|
126
|
-
"/snap/bin"
|
127
|
-
]
|
128
|
-
|
129
|
-
elif system == "darwin": # macOS
|
130
|
-
search_paths = [
|
131
|
-
"/opt/homebrew/bin", # M1 Mac
|
132
|
-
"/usr/local/bin", # Intel Mac
|
133
|
-
"/opt/local/bin" # MacPorts
|
134
|
-
]
|
135
|
-
|
136
|
-
elif system == "windows":
|
137
|
-
search_paths = [
|
138
|
-
os.path.expandvars(r"%ProgramFiles%\Multipass"),
|
139
|
-
os.path.expandvars(r"%ProgramFiles(x86)%\Multipass"),
|
140
|
-
os.path.expandvars(r"%LocalAppData%\Multipass")
|
141
|
-
]
|
142
|
-
|
143
|
-
else:
|
144
|
-
search_paths = ["/usr/local/bin", "/usr/bin"]
|
145
|
-
|
146
|
-
# Search for multipass binary in OS-specific paths
|
147
|
-
for directory in search_paths:
|
148
|
-
path = os.path.join(directory, binary_name)
|
149
|
-
if os.path.isfile(path) and os.access(path, os.X_OK):
|
150
|
-
return path
|
151
|
-
|
152
|
-
# OS-specific installation instructions
|
153
|
-
if system == "linux":
|
154
|
-
raise ValueError(
|
155
|
-
"Multipass binary not found. Please install using:\n"
|
156
|
-
"sudo snap install multipass\n"
|
157
|
-
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
158
|
-
)
|
159
|
-
elif system == "darwin":
|
160
|
-
raise ValueError(
|
161
|
-
"Multipass binary not found. Please install using:\n"
|
162
|
-
"brew install multipass\n"
|
163
|
-
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
164
|
-
)
|
165
|
-
elif system == "windows":
|
166
|
-
raise ValueError(
|
167
|
-
"Multipass binary not found. Please install from:\n"
|
168
|
-
"Microsoft Store or https://multipass.run/download/windows\n"
|
169
|
-
"Or set GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
170
|
-
)
|
171
|
-
else:
|
172
|
-
raise ValueError(
|
173
|
-
"Multipass binary not found. Please install Multipass or set "
|
174
|
-
"GOLEM_PROVIDER_MULTIPASS_BINARY_PATH to your Multipass binary path."
|
175
|
-
)
|
176
|
-
|
177
|
-
# Validate the path
|
178
|
-
if not os.path.isfile(path):
|
179
|
-
raise ValueError(f"Multipass binary not found at: {path}")
|
180
|
-
if not os.access(path, os.X_OK):
|
181
|
-
raise ValueError(f"Multipass binary at {path} is not executable")
|
182
|
-
return path
|
183
|
-
|
184
|
-
# Proxy Settings
|
185
|
-
PORT_RANGE_START: int = 50800
|
186
|
-
PORT_RANGE_END: int = 50900
|
187
|
-
PROXY_STATE_DIR: str = ""
|
188
|
-
PUBLIC_IP: Optional[str] = None
|
189
|
-
|
190
|
-
@validator("PROXY_STATE_DIR", pre=True)
|
191
|
-
def resolve_proxy_state_dir(cls, v: str) -> str:
|
192
|
-
"""Resolve proxy state directory path."""
|
193
|
-
if not v:
|
194
|
-
return str(Path.home() / ".golem" / "provider" / "proxy")
|
195
|
-
path = Path(v)
|
196
|
-
if not path.is_absolute():
|
197
|
-
path = Path.home() / path
|
198
|
-
return str(path)
|
199
|
-
|
200
|
-
@validator("PUBLIC_IP", pre=True)
|
201
|
-
def get_public_ip(cls, v: Optional[str]) -> Optional[str]:
|
202
|
-
"""Get public IP if set to 'auto'."""
|
203
|
-
if v == "auto":
|
204
|
-
try:
|
205
|
-
import requests
|
206
|
-
response = requests.get("https://api.ipify.org")
|
207
|
-
return response.text.strip()
|
208
|
-
except Exception:
|
209
|
-
return None
|
210
|
-
return v
|
211
|
-
|
212
|
-
class Config:
|
213
|
-
env_prefix = "GOLEM_PROVIDER_"
|
214
|
-
case_sensitive = True
|
215
|
-
|
216
|
-
|
217
|
-
# Global settings instance
|
218
|
-
settings = Settings()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{golem_vm_provider-0.1.12 → golem_vm_provider-0.1.13}/provider/discovery/resource_tracker.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|