golem-vm-provider 0.1.18__py3-none-any.whl → 0.1.20__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.
- {golem_vm_provider-0.1.18.dist-info → golem_vm_provider-0.1.20.dist-info}/METADATA +1 -1
- {golem_vm_provider-0.1.18.dist-info → golem_vm_provider-0.1.20.dist-info}/RECORD +7 -7
- provider/main.py +6 -2
- provider/vm/multipass.py +4 -1
- provider/vm/proxy_manager.py +43 -21
- {golem_vm_provider-0.1.18.dist-info → golem_vm_provider-0.1.20.dist-info}/WHEEL +0 -0
- {golem_vm_provider-0.1.18.dist-info → golem_vm_provider-0.1.20.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@ provider/config.py,sha256=-Cu05ebOjUbhnh5iv3raQ7Z79HMhZ9EcRIRrZVW3Ino,14513
|
|
6
6
|
provider/discovery/__init__.py,sha256=VR3NRoQtZRH5Vs8FG7jnGLR7p7wn7XeZdLaBb3t8e1g,123
|
7
7
|
provider/discovery/advertiser.py,sha256=yv7RbRf1K43qOLAEa2Olj9hhN8etl2qsBuoHok0xoVs,6784
|
8
8
|
provider/discovery/resource_tracker.py,sha256=8dYhJxoe_jLRwisHoA0jr575YhUKmLIqSXfW88KshcQ,6000
|
9
|
-
provider/main.py,sha256=
|
9
|
+
provider/main.py,sha256=jl80WRIvsvfbHFvoPZqtIhFDUJm0andcyXqUu6Dfi2E,9389
|
10
10
|
provider/network/port_verifier.py,sha256=AUtBGuZdfq9Jt4BRDuYesh5YEmwneEzYUgIw-uajZhA,12977
|
11
11
|
provider/security/ethereum.py,sha256=SDRDbcjynbVy44kNnxlDcYLL0BZ3Qnc0DvmneQ-WKLE,1383
|
12
12
|
provider/utils/ascii_art.py,sha256=ykBFsztk57GIiz1NJ-EII5UvN74iECqQL4h9VmiW6Z8,3161
|
@@ -17,11 +17,11 @@ provider/utils/setup.py,sha256=Z5dLuBQkb5vdoQsu1HJZwXmu9NWsiBYJ7Vq9-C-_tY8,2932
|
|
17
17
|
provider/vm/__init__.py,sha256=JGs50tUmzOR1rQ_w4fMY_3XWylmiA1G7KKWZkVw51mY,501
|
18
18
|
provider/vm/cloud_init.py,sha256=E5dDH7dqStRcJNDfbarBBe83-c9N63W8B5ycIrHI8eU,4627
|
19
19
|
provider/vm/models.py,sha256=zkfvP5Z50SPDNajwZTt9NTDIMRQIsZLvSOsuirHEcJM,6256
|
20
|
-
provider/vm/multipass.py,sha256=
|
20
|
+
provider/vm/multipass.py,sha256=RufJbl39d_mEXruX0gX1zCmEEiQ_DytPXgW6F1qVQaM,16667
|
21
21
|
provider/vm/name_mapper.py,sha256=MrshNeJ4Dw-WBsyiIVcn9N5xyOxaBKX4Yqhyh_m5IFg,4103
|
22
22
|
provider/vm/port_manager.py,sha256=d03uwU76vx6LgADMN8ffBT9t400XQ3vtYlXr6cLIFN0,9831
|
23
|
-
provider/vm/proxy_manager.py,sha256=
|
24
|
-
golem_vm_provider-0.1.
|
25
|
-
golem_vm_provider-0.1.
|
26
|
-
golem_vm_provider-0.1.
|
27
|
-
golem_vm_provider-0.1.
|
23
|
+
provider/vm/proxy_manager.py,sha256=ZrLm6S6aaCvmwYmqd_9ne1_3T7M8qxoNDdAtYX8ZDRE,11704
|
24
|
+
golem_vm_provider-0.1.20.dist-info/METADATA,sha256=jKbkVW9HxnSHl7I0qGSFqV799kPjq7LGv54HwHJBRx0,10594
|
25
|
+
golem_vm_provider-0.1.20.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
26
|
+
golem_vm_provider-0.1.20.dist-info/entry_points.txt,sha256=E4rCWo_Do_2zCG_GewNuftfVlHF_8b_OvioZre0dfeA,54
|
27
|
+
golem_vm_provider-0.1.20.dist-info/RECORD,,
|
provider/main.py
CHANGED
@@ -31,11 +31,15 @@ async def setup_provider() -> None:
|
|
31
31
|
provider = MultipassProvider(resource_tracker, port_manager=port_manager)
|
32
32
|
try:
|
33
33
|
await asyncio.wait_for(provider.initialize(), timeout=30)
|
34
|
-
app.state.provider = provider
|
35
34
|
|
36
|
-
# Store proxy manager
|
35
|
+
# Store provider and proxy manager references
|
36
|
+
app.state.provider = provider
|
37
37
|
app.state.proxy_manager = provider.proxy_manager
|
38
38
|
|
39
|
+
# Restore proxy configurations
|
40
|
+
logger.process("🔄 Restoring proxy configurations...")
|
41
|
+
await app.state.proxy_manager._load_state()
|
42
|
+
|
39
43
|
except asyncio.TimeoutError:
|
40
44
|
logger.error("Provider initialization timed out")
|
41
45
|
raise
|
provider/vm/multipass.py
CHANGED
@@ -37,8 +37,11 @@ class MultipassProvider(VMProvider):
|
|
37
37
|
self.vm_data_dir.mkdir(parents=True, exist_ok=True)
|
38
38
|
|
39
39
|
# Initialize managers
|
40
|
-
self.proxy_manager = PythonProxyManager(port_manager=port_manager)
|
41
40
|
self.name_mapper = VMNameMapper(self.vm_data_dir / "vm_names.json")
|
41
|
+
self.proxy_manager = PythonProxyManager(
|
42
|
+
port_manager=port_manager,
|
43
|
+
name_mapper=self.name_mapper
|
44
|
+
)
|
42
45
|
|
43
46
|
def _verify_installation(self) -> None:
|
44
47
|
"""Verify multipass is installed and get version."""
|
provider/vm/proxy_manager.py
CHANGED
@@ -147,42 +147,64 @@ class PythonProxyManager:
|
|
147
147
|
def __init__(
|
148
148
|
self,
|
149
149
|
port_manager: PortManager,
|
150
|
+
name_mapper: "VMNameMapper",
|
150
151
|
state_file: Optional[str] = None
|
151
152
|
):
|
152
153
|
"""Initialize the proxy manager.
|
153
154
|
|
154
155
|
Args:
|
155
156
|
port_manager: Port allocation manager
|
157
|
+
name_mapper: VM name mapping manager
|
156
158
|
state_file: Path to persist proxy state
|
157
159
|
"""
|
158
160
|
self.port_manager = port_manager
|
161
|
+
self.name_mapper = name_mapper
|
159
162
|
self.state_file = state_file or os.path.expanduser("~/.golem/provider/proxy_state.json")
|
160
|
-
self._proxies: Dict[str, ProxyServer] = {} #
|
161
|
-
|
163
|
+
self._proxies: Dict[str, ProxyServer] = {} # multipass_name -> ProxyServer
|
164
|
+
# Note: _load_state is now async and will be called explicitly during provider setup
|
162
165
|
|
163
|
-
def _load_state(self) -> None:
|
164
|
-
"""Load proxy state from file."""
|
166
|
+
async def _load_state(self) -> None:
|
167
|
+
"""Load and restore proxy state from file."""
|
165
168
|
try:
|
166
169
|
state_path = Path(self.state_file)
|
167
170
|
if state_path.exists():
|
168
171
|
with open(state_path, 'r') as f:
|
169
172
|
state = json.load(f)
|
170
|
-
#
|
171
|
-
|
172
|
-
|
173
|
+
# Restore proxy servers from saved state
|
174
|
+
restore_tasks = []
|
175
|
+
for requestor_name, proxy_info in state.items():
|
176
|
+
# Get current multipass name for the requestor's VM
|
177
|
+
multipass_name = await self.name_mapper.get_multipass_name(requestor_name)
|
178
|
+
if multipass_name:
|
179
|
+
# Create task to restore proxy
|
180
|
+
task = self.add_vm(
|
181
|
+
vm_id=multipass_name, # Use multipass name for internal tracking
|
182
|
+
vm_ip=proxy_info['target'],
|
183
|
+
port=proxy_info['port']
|
184
|
+
)
|
185
|
+
restore_tasks.append(task)
|
186
|
+
else:
|
187
|
+
logger.warning(f"No multipass name found for requestor VM {requestor_name}")
|
188
|
+
|
189
|
+
# Wait for all proxies to be restored
|
190
|
+
if restore_tasks:
|
191
|
+
results = await asyncio.gather(*restore_tasks, return_exceptions=True)
|
192
|
+
successful = sum(1 for r in results if r is True)
|
193
|
+
logger.info(f"Restored {successful}/{len(state)} proxy configurations")
|
173
194
|
except Exception as e:
|
174
195
|
logger.error(f"Failed to load proxy state: {e}")
|
175
196
|
|
176
|
-
def _save_state(self) -> None:
|
177
|
-
"""Save current proxy state to file."""
|
197
|
+
async def _save_state(self) -> None:
|
198
|
+
"""Save current proxy state to file using requestor names."""
|
178
199
|
try:
|
179
|
-
state = {
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
200
|
+
state = {}
|
201
|
+
for multipass_name, proxy in self._proxies.items():
|
202
|
+
requestor_name = await self.name_mapper.get_requestor_name(multipass_name)
|
203
|
+
if requestor_name:
|
204
|
+
state[requestor_name] = {
|
205
|
+
'port': proxy.listen_port,
|
206
|
+
'target': proxy.target_host
|
207
|
+
}
|
186
208
|
os.makedirs(os.path.dirname(self.state_file), exist_ok=True)
|
187
209
|
with open(self.state_file, 'w') as f:
|
188
210
|
json.dump(state, f)
|
@@ -193,7 +215,7 @@ class PythonProxyManager:
|
|
193
215
|
"""Add proxy configuration for a new VM.
|
194
216
|
|
195
217
|
Args:
|
196
|
-
vm_id: Unique identifier for the VM
|
218
|
+
vm_id: Unique identifier for the VM (multipass name)
|
197
219
|
vm_ip: IP address of the VM
|
198
220
|
port: Optional specific port to use, if not provided one will be allocated
|
199
221
|
|
@@ -213,7 +235,7 @@ class PythonProxyManager:
|
|
213
235
|
await proxy.start()
|
214
236
|
|
215
237
|
self._proxies[vm_id] = proxy
|
216
|
-
self._save_state()
|
238
|
+
await self._save_state()
|
217
239
|
|
218
240
|
logger.info(f"Started proxy for VM {vm_id} on port {port}")
|
219
241
|
return True
|
@@ -229,14 +251,14 @@ class PythonProxyManager:
|
|
229
251
|
"""Remove proxy configuration for a VM.
|
230
252
|
|
231
253
|
Args:
|
232
|
-
vm_id: Unique identifier for the VM
|
254
|
+
vm_id: Unique identifier for the VM (multipass name)
|
233
255
|
"""
|
234
256
|
try:
|
235
257
|
if vm_id in self._proxies:
|
236
258
|
proxy = self._proxies.pop(vm_id)
|
237
259
|
await proxy.stop()
|
238
260
|
self.port_manager.deallocate_port(vm_id)
|
239
|
-
self._save_state()
|
261
|
+
await self._save_state()
|
240
262
|
logger.info(f"Removed proxy for VM {vm_id}")
|
241
263
|
except Exception as e:
|
242
264
|
logger.error(f"Failed to remove proxy for VM {vm_id}: {e}")
|
@@ -257,7 +279,7 @@ class PythonProxyManager:
|
|
257
279
|
cleanup_errors.append(f"Failed to remove proxy for VM {vm_id}: {e}")
|
258
280
|
|
259
281
|
try:
|
260
|
-
self._save_state()
|
282
|
+
await self._save_state()
|
261
283
|
except Exception as e:
|
262
284
|
cleanup_errors.append(f"Failed to save state: {e}")
|
263
285
|
|
File without changes
|
File without changes
|