golem-vm-provider 0.1.59__py3-none-any.whl → 0.1.60__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: golem-vm-provider
3
- Version: 0.1.59
3
+ Version: 0.1.60
4
4
  Summary: VM on Golem Provider Node - Run your own provider node to offer VMs on the Golem Network
5
5
  Keywords: golem,vm,provider,cloud,decentralized
6
6
  Author: Phillip Jensen
@@ -1,7 +1,7 @@
1
1
  provider/__init__.py,sha256=HO1fkPpZqPO3z8O8-eVIyx8xXSMIVuTR_b1YF0RtXOg,45
2
2
  provider/api/__init__.py,sha256=ssX1ugDqEPt8Fn04IymgmG-Ev8PiXLsCSaiZVvHQnec,344
3
3
  provider/api/models.py,sha256=LcEWVUE8zvX_9ByyzbyoZGiDIJf_4MLDYqX7_nRO6B0,4754
4
- provider/api/routes.py,sha256=4luagwoqW84PPvQRE3LR-W5XfoHpAbG0NK2fWnE1qSo,20228
4
+ provider/api/routes.py,sha256=egZVUyQ8MRFB_i_wmMIyZJzakddYVy0w0K8LPtNyVYw,20617
5
5
  provider/config.py,sha256=65L47ByUXoyvhD5DSsIYbM3yjlwFB5j4L6-__kAlkW0,29186
6
6
  provider/container.py,sha256=QCYlIvR1m0ediA9PwJ_OXwZU3Ye-R7G6ZGsXFDji_jQ,3957
7
7
  provider/data/deployments/l2.json,sha256=XTNN2C5LkBfp4YbDKdUKfWMdp1fKnfv8D3TgcwVWxtQ,249
@@ -14,7 +14,7 @@ provider/discovery/resource_monitor.py,sha256=AmiEc7yBGEGXCunQ-QKmVgosDX3gOhK1Y5
14
14
  provider/discovery/resource_tracker.py,sha256=MP7IXd3aIMsjB4xz5Oj9zFDTEnvrnw-Cyxpl33xcJcc,6006
15
15
  provider/discovery/service.py,sha256=0H4H8HuFP52xE6lrXTOUHfvaIVjbT1uzcnlPxEswjNc,1000
16
16
  provider/jobs/store.py,sha256=gLT5tWS7RmxGFfpjriECl4Kfn7osCP2woA8plKTZM4g,3958
17
- provider/main.py,sha256=CFMlTeXAkTnE8zRVEGOdkbICzFYwwoZUjBPsUOLJsoM,64479
17
+ provider/main.py,sha256=7SGPH4RcS1K7aPf83xHaCKR0s_J-WfTJx-O8UwJzASU,64551
18
18
  provider/network/port_verifier.py,sha256=mlSzr9Z-W5Z5mL3EYg4zemgGoi8Z5ebNoeFgLGRaoH4,13253
19
19
  provider/payments/blockchain_service.py,sha256=4GrzDKwCSUVoENqjD4RLyJ0qwBOJKMyVk5Li-XNsyTc,3567
20
20
  provider/payments/monitor.py,sha256=qBykIXD_Fks7_VS7Mh3Zb99HMC4x4Z_2PlYaMyfBORc,6069
@@ -34,13 +34,13 @@ provider/vm/__init__.py,sha256=LJL504QGbqZvBbMN3G9ixMgAwvOWAKW37zUm_EiaW9M,508
34
34
  provider/vm/cloud_init.py,sha256=E5dDH7dqStRcJNDfbarBBe83-c9N63W8B5ycIrHI8eU,4627
35
35
  provider/vm/models.py,sha256=hNeXgOnXWyeSiYt07Pdks0B20cDi_VC8jV-tCxULNng,6350
36
36
  provider/vm/multipass.py,sha256=rjO3GtuS4O_wXyYXSUiDGWYtQV2LpGxm6kITrA-ghBQ,617
37
- provider/vm/multipass_adapter.py,sha256=HW4_7cs3O_SCi1unfIvhC44duO561bpO6yrHGkqhLQA,11578
37
+ provider/vm/multipass_adapter.py,sha256=CQlsWyI2lANVwOin7qujxRZEyMwfQNnQSxyqJNY3q2Q,12896
38
38
  provider/vm/name_mapper.py,sha256=14nKfCjJ1WkXfC4vnCYIxNGQUwcl2vcxrJYUAz4fL40,4073
39
39
  provider/vm/port_manager.py,sha256=iYSwjTjD_ziOhG8aI7juKHw1OwwRUTJQyQoRUNQvz9w,12514
40
40
  provider/vm/provider.py,sha256=A7QN89EJjcSS40_SmKeinG1Jp_NGffJaLse-XdKciAs,1164
41
41
  provider/vm/proxy_manager.py,sha256=n4NTsyz2rtrvjtf_ceKBk-g2q_mzqPwruB1q7UlQVBc,14928
42
42
  provider/vm/service.py,sha256=Ki4SGNIZUq3XmaPMwAOoNzdZzKQsmFXid374wgjFPes,4636
43
- golem_vm_provider-0.1.59.dist-info/METADATA,sha256=gk1kKhCSdXFCqD5sHNC81F8nl3PtgNSp1Rwxwpk2CXg,21221
44
- golem_vm_provider-0.1.59.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
45
- golem_vm_provider-0.1.59.dist-info/entry_points.txt,sha256=5Jiie1dIXygmxmDW66bKKxQpmBLJ7leSKRrb8bkQALw,52
46
- golem_vm_provider-0.1.59.dist-info/RECORD,,
43
+ golem_vm_provider-0.1.60.dist-info/METADATA,sha256=8nPSP0__wjWtbFyX9espYR6kHs1jqp6B9BndLOizr0E,21221
44
+ golem_vm_provider-0.1.60.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
45
+ golem_vm_provider-0.1.60.dist-info/entry_points.txt,sha256=5Jiie1dIXygmxmDW66bKKxQpmBLJ7leSKRrb8bkQALw,52
46
+ golem_vm_provider-0.1.60.dist-info/RECORD,,
provider/api/routes.py CHANGED
@@ -31,6 +31,12 @@ from ..vm.multipass_adapter import MultipassError
31
31
  logger = setup_logger(__name__)
32
32
  router = APIRouter()
33
33
 
34
+ # Expose Settings class at module scope for tests to monkeypatch default deployment lookup
35
+ try:
36
+ from ..config import Settings as _Cfg # type: ignore
37
+ except Exception: # noqa: BLE001
38
+ _Cfg = None # type: ignore
39
+
34
40
  # Job status persisted in SQLite via JobStore (see Container.job_store)
35
41
 
36
42
 
@@ -56,8 +62,10 @@ async def create_vm(
56
62
  if spa and spa != "0x0000000000000000000000000000000000000000":
57
63
  if os.environ.get("PYTEST_CURRENT_TEST"):
58
64
  try:
59
- from ..config import Settings as _Cfg # type: ignore
60
- default_spa, _ = _Cfg._load_l2_deployment() # type: ignore[attr-defined]
65
+ if _Cfg is not None:
66
+ default_spa, _ = _Cfg._load_l2_deployment() # type: ignore[attr-defined]
67
+ else:
68
+ default_spa = None
61
69
  except Exception:
62
70
  default_spa = None
63
71
  if not default_spa or spa.lower() != default_spa.lower():
@@ -302,6 +310,8 @@ async def provider_info(settings: Any = Depends(Provide[Container.config])) -> P
302
310
  provider_id=settings["PROVIDER_ID"],
303
311
  stream_payment_address=settings["STREAM_PAYMENT_ADDRESS"],
304
312
  glm_token_address=settings["GLM_TOKEN_ADDRESS"],
313
+ # Provide ETH-focused alias for clients; keep legacy field too
314
+ eth_token_address=settings["GLM_TOKEN_ADDRESS"],
305
315
  ip_address=ip_addr,
306
316
  country=(settings.get("PROVIDER_COUNTRY") if isinstance(settings, dict) else getattr(settings, "PROVIDER_COUNTRY", None)),
307
317
  platform=platform_str,
provider/main.py CHANGED
@@ -15,6 +15,7 @@ if "--json" in _sys.argv:
15
15
 
16
16
  # Defer heavy local imports (may import config) until after we decide on silence
17
17
  from .container import Container
18
+ from .config import settings # used by pricing CLI and server commands
18
19
  from .service import ProviderService
19
20
 
20
21
  logger = setup_logger(__name__)
@@ -32,6 +32,26 @@ class MultipassAdapter(VMProvider):
32
32
  self.proxy_manager = proxy_manager
33
33
  self.name_mapper = name_mapper
34
34
 
35
+ @staticmethod
36
+ def _safe_int(value, default: int = 0) -> int:
37
+ """Best-effort int conversion that treats missing/blank values as default.
38
+
39
+ Multipass may return empty strings for numeric fields (e.g., when a VM is
40
+ stopped). This helper prevents ValueError by mapping '', None, or
41
+ unparsable values to a sensible default.
42
+ """
43
+ try:
44
+ if value is None:
45
+ return default
46
+ if isinstance(value, str):
47
+ v = value.strip()
48
+ if v == "":
49
+ return default
50
+ return int(v)
51
+ return int(value)
52
+ except (ValueError, TypeError):
53
+ return default
54
+
35
55
  async def _run_multipass(self, args: List[str], check: bool = True) -> subprocess.CompletedProcess:
36
56
  """Run a multipass command."""
37
57
  # Commands that produce JSON or version info that we need to parse.
@@ -160,8 +180,8 @@ class MultipassAdapter(VMProvider):
160
180
  vms: List[VMInfo] = []
161
181
  for requestor_name, multipass_name in list(all_mappings.items()):
162
182
  try:
163
- # get_vm_status expects multipass_name
164
- vm_info = await self.get_vm_status(multipass_name)
183
+ # Pass requestor id; get_vm_status accepts either id
184
+ vm_info = await self.get_vm_status(requestor_name)
165
185
  vms.append(vm_info)
166
186
  except VMNotFoundError:
167
187
  logger.warning(
@@ -188,30 +208,40 @@ class MultipassAdapter(VMProvider):
188
208
  await self._run_multipass(["stop", multipass_name])
189
209
  return await self.get_vm_status(multipass_name)
190
210
 
191
- async def get_vm_status(self, multipass_name: str) -> VMInfo:
192
- """Get the status of a VM."""
211
+ async def get_vm_status(self, name_or_id: str) -> VMInfo:
212
+ """Get VM status by multipass name or requestor id."""
213
+ # Resolve identifiers flexibly
214
+ requestor_name = await self.name_mapper.get_requestor_name(name_or_id)
215
+ if requestor_name:
216
+ multipass_name = name_or_id
217
+ else:
218
+ multipass_name = await self.name_mapper.get_multipass_name(name_or_id)
219
+ if not multipass_name:
220
+ raise VMNotFoundError(f"VM {name_or_id} mapping not found")
221
+ requestor_name = name_or_id
193
222
  try:
194
223
  info = await self._get_vm_info(multipass_name)
195
224
  except MultipassError:
196
225
  raise VMNotFoundError(f"VM {multipass_name} not found in multipass")
197
226
 
198
- requestor_name = await self.name_mapper.get_requestor_name(multipass_name)
199
- if not requestor_name:
200
- raise VMNotFoundError(f"Mapping for VM {multipass_name} not found")
201
-
202
227
  ipv4 = info.get("ipv4")
203
228
  ip_address = ipv4[0] if ipv4 else None
204
229
  logger.debug(f"Parsed VM info for {requestor_name}: {info}")
205
230
 
206
231
  disks_info = info.get("disks", {})
207
- total_storage = sum(int(disk.get("total", 0)) for disk in disks_info.values())
232
+ total_storage = 0
233
+ for disk in disks_info.values():
234
+ total_storage += self._safe_int(disk.get("total"), 0)
235
+
236
+ # Memory reported by multipass is in bytes; default to 1 GiB if missing/blank
237
+ mem_total_bytes = self._safe_int(info.get("memory", {}).get("total"), 1024**3)
208
238
  vm_info_obj = VMInfo(
209
239
  id=requestor_name,
210
240
  name=requestor_name,
211
241
  status=VMStatus(info["state"].lower()),
212
242
  resources=VMResources(
213
- cpu=int(info.get("cpu_count", "1")),
214
- memory=round(info.get("memory", {}).get("total", 1024**3) / (1024**3)),
243
+ cpu=self._safe_int(info.get("cpu_count"), 1),
244
+ memory=round(mem_total_bytes / (1024**3)),
215
245
  storage=round(total_storage / (1024**3)) if total_storage > 0 else 10
216
246
  ),
217
247
  ip_address=ip_address,
@@ -228,10 +258,13 @@ class MultipassAdapter(VMProvider):
228
258
  try:
229
259
  info = await self._get_vm_info(multipass_name)
230
260
  disks_info = info.get("disks", {})
231
- total_storage = sum(int(disk.get("total", 0)) for disk in disks_info.values())
261
+ total_storage = 0
262
+ for disk in disks_info.values():
263
+ total_storage += self._safe_int(disk.get("total"), 0)
264
+ mem_total_bytes = self._safe_int(info.get("memory", {}).get("total"), 1024**3)
232
265
  vm_resources[requestor_name] = VMResources(
233
- cpu=int(info.get("cpu_count", "1")),
234
- memory=round(info.get("memory", {}).get("total", 1024**3) / (1024**3)),
266
+ cpu=self._safe_int(info.get("cpu_count"), 1),
267
+ memory=round(mem_total_bytes / (1024**3)),
235
268
  storage=round(total_storage / (1024**3)) if total_storage > 0 else 10
236
269
  )
237
270
  except (MultipassError, VMNotFoundError):