golem-vm-provider 0.1.17__py3-none-any.whl → 0.1.18__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.17
3
+ Version: 0.1.18
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
@@ -2,7 +2,7 @@ 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=JOzoNf1oE5N97UqTN5xuIrTkqn2tCHqPDaIzGA3jUyo,3513
4
4
  provider/api/routes.py,sha256=P27RQvNqFWn6PacRwr1PaVz-yv5KAWsp9KeORejkXSI,6452
5
- provider/config.py,sha256=btSyU6cB6z8o9nHWpNEOBDxKqsEha1yStM-6of3Np0s,13237
5
+ 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
@@ -13,6 +13,7 @@ provider/utils/ascii_art.py,sha256=ykBFsztk57GIiz1NJ-EII5UvN74iECqQL4h9VmiW6Z8,3
13
13
  provider/utils/logging.py,sha256=C_elr0sJROHKQgErYpHJQvfujgh0k4Zf2gg8ZKfrmVk,2590
14
14
  provider/utils/port_display.py,sha256=5d_604Eo-82dqx_yV2ZScq7bKQ8IsXacc-yXC_KAz3A,11031
15
15
  provider/utils/retry.py,sha256=ekP2ucaSJNN-lBcrIvyHa4QYPKNITMl1a5V1X6BBvsw,1560
16
+ provider/utils/setup.py,sha256=Z5dLuBQkb5vdoQsu1HJZwXmu9NWsiBYJ7Vq9-C-_tY8,2932
16
17
  provider/vm/__init__.py,sha256=JGs50tUmzOR1rQ_w4fMY_3XWylmiA1G7KKWZkVw51mY,501
17
18
  provider/vm/cloud_init.py,sha256=E5dDH7dqStRcJNDfbarBBe83-c9N63W8B5ycIrHI8eU,4627
18
19
  provider/vm/models.py,sha256=zkfvP5Z50SPDNajwZTt9NTDIMRQIsZLvSOsuirHEcJM,6256
@@ -20,7 +21,7 @@ provider/vm/multipass.py,sha256=FOcsfcJ-NrgBg_fvq_CKOKsQ0xOmk7Z34KXi3ag_Vl8,1660
20
21
  provider/vm/name_mapper.py,sha256=MrshNeJ4Dw-WBsyiIVcn9N5xyOxaBKX4Yqhyh_m5IFg,4103
21
22
  provider/vm/port_manager.py,sha256=d03uwU76vx6LgADMN8ffBT9t400XQ3vtYlXr6cLIFN0,9831
22
23
  provider/vm/proxy_manager.py,sha256=cu0FPPbeCc3CR6NRE_CnLjiRg7xVdSFUylVUOL1g1sI,10154
23
- golem_vm_provider-0.1.17.dist-info/METADATA,sha256=Lu9EpHlgFmOQP56l89vLyowyM0j48TI5BTGfT_EQxtQ,10594
24
- golem_vm_provider-0.1.17.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
25
- golem_vm_provider-0.1.17.dist-info/entry_points.txt,sha256=E4rCWo_Do_2zCG_GewNuftfVlHF_8b_OvioZre0dfeA,54
26
- golem_vm_provider-0.1.17.dist-info/RECORD,,
24
+ golem_vm_provider-0.1.18.dist-info/METADATA,sha256=8YfU5Z2xOi0URBANotJQK27x2zJvUz5o2rzVl5hRHt0,10594
25
+ golem_vm_provider-0.1.18.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
26
+ golem_vm_provider-0.1.18.dist-info/entry_points.txt,sha256=E4rCWo_Do_2zCG_GewNuftfVlHF_8b_OvioZre0dfeA,54
27
+ golem_vm_provider-0.1.18.dist-info/RECORD,,
provider/config.py CHANGED
@@ -64,6 +64,7 @@ class Settings(BaseSettings):
64
64
  """Resolve and create cloud-init directory path."""
65
65
  import platform
66
66
  import tempfile
67
+ from .utils.setup import setup_cloud_init_dir, check_setup_needed, mark_setup_complete
67
68
 
68
69
  def verify_dir_permissions(path: Path) -> bool:
69
70
  """Verify directory has correct permissions and is accessible."""
@@ -86,15 +87,32 @@ class Settings(BaseSettings):
86
87
  if system == "linux" and Path("/snap/bin/multipass").exists():
87
88
  # Linux with snap
88
89
  path = Path("/var/snap/multipass/common/cloud-init")
90
+
91
+ # Check if we need to set up permissions
92
+ if check_setup_needed():
93
+ logger.info("First run detected, setting up cloud-init directory...")
94
+ success, error = setup_cloud_init_dir(path)
95
+ if success:
96
+ logger.info("✓ Cloud-init directory setup complete")
97
+ mark_setup_complete()
98
+ else:
99
+ logger.error(f"Failed to set up cloud-init directory: {error}")
100
+ logger.error("\nTo fix this manually, run these commands:")
101
+ logger.error(" sudo mkdir -p /var/snap/multipass/common/cloud-init")
102
+ logger.error(" sudo chown -R $USER:$USER /var/snap/multipass/common/cloud-init")
103
+ logger.error(" sudo chmod -R 755 /var/snap/multipass/common/cloud-init\n")
104
+ # Fall back to user's home directory
105
+ path = Path.home() / ".local" / "share" / "golem" / "provider" / "cloud-init"
106
+
89
107
  elif system == "linux":
90
108
  # Linux without snap
91
- path = Path("/var/lib/multipass/cloud-init")
109
+ path = Path.home() / ".local" / "share" / "golem" / "provider" / "cloud-init"
92
110
  elif system == "darwin":
93
111
  # macOS
94
- path = Path("/Library/Application Support/multipass/cloud-init")
112
+ path = Path.home() / "Library" / "Application Support" / "golem" / "provider" / "cloud-init"
95
113
  elif system == "windows":
96
114
  # Windows
97
- path = Path(os.path.expandvars("%ProgramData%\\Multipass\\cloud-init"))
115
+ path = Path(os.path.expandvars("%LOCALAPPDATA%")) / "golem" / "provider" / "cloud-init"
98
116
  else:
99
117
  path = Path.home() / ".golem" / "provider" / "cloud-init"
100
118
 
@@ -0,0 +1,100 @@
1
+ import os
2
+ import subprocess
3
+ import platform
4
+ from pathlib import Path
5
+ from typing import Tuple
6
+
7
+ from .logging import setup_logger
8
+
9
+ logger = setup_logger(__name__)
10
+
11
+ def run_sudo_command(cmd: str) -> Tuple[bool, str]:
12
+ """Run a command with sudo.
13
+
14
+ Args:
15
+ cmd: Command to run
16
+
17
+ Returns:
18
+ Tuple of (success, error_message)
19
+ """
20
+ try:
21
+ # Try non-interactive sudo first
22
+ result = subprocess.run(
23
+ f"sudo -n {cmd}",
24
+ shell=True,
25
+ capture_output=True,
26
+ text=True
27
+ )
28
+ if result.returncode == 0:
29
+ return True, ""
30
+
31
+ # If that fails, try interactive sudo
32
+ logger.warning("Non-interactive sudo failed, will prompt for password")
33
+ result = subprocess.run(
34
+ f"sudo {cmd}",
35
+ shell=True,
36
+ capture_output=True,
37
+ text=True
38
+ )
39
+ if result.returncode == 0:
40
+ return True, ""
41
+
42
+ return False, result.stderr
43
+
44
+ except Exception as e:
45
+ return False, str(e)
46
+
47
+ def setup_cloud_init_dir(path: Path) -> Tuple[bool, str]:
48
+ """Set up cloud-init directory with correct permissions.
49
+
50
+ Args:
51
+ path: Path to cloud-init directory
52
+
53
+ Returns:
54
+ Tuple of (success, error_message)
55
+ """
56
+ if platform.system().lower() != "linux" or not Path("/snap/bin/multipass").exists():
57
+ # Only needed for Linux with snap
58
+ return True, ""
59
+
60
+ try:
61
+ # Create directory
62
+ success, error = run_sudo_command(f"mkdir -p {path}")
63
+ if not success:
64
+ return False, f"Failed to create directory: {error}"
65
+
66
+ # Set ownership
67
+ user = os.environ.get("USER", os.environ.get("USERNAME"))
68
+ success, error = run_sudo_command(f"chown -R {user}:{user} {path}")
69
+ if not success:
70
+ return False, f"Failed to set ownership: {error}"
71
+
72
+ # Set permissions
73
+ success, error = run_sudo_command(f"chmod -R 755 {path}")
74
+ if not success:
75
+ return False, f"Failed to set permissions: {error}"
76
+
77
+ return True, ""
78
+
79
+ except Exception as e:
80
+ return False, str(e)
81
+
82
+ def check_setup_needed() -> bool:
83
+ """Check if setup is needed.
84
+
85
+ Returns:
86
+ True if setup is needed, False otherwise
87
+ """
88
+ # Only needed for Linux with snap
89
+ if platform.system().lower() != "linux" or not Path("/snap/bin/multipass").exists():
90
+ return False
91
+
92
+ # Check if setup has already been completed
93
+ setup_flag = Path.home() / ".golem" / "provider" / ".setup-complete"
94
+ return not setup_flag.exists()
95
+
96
+ def mark_setup_complete() -> None:
97
+ """Mark setup as complete."""
98
+ setup_flag = Path.home() / ".golem" / "provider" / ".setup-complete"
99
+ setup_flag.parent.mkdir(parents=True, exist_ok=True)
100
+ setup_flag.touch()