clouditia-manager 1.2.2__tar.gz → 1.3.2__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.
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/PKG-INFO +50 -9
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/README.md +49 -8
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager/client.py +72 -9
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/PKG-INFO +50 -9
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/setup.py +1 -1
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager/__init__.py +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager/exceptions.py +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/SOURCES.txt +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/dependency_links.txt +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/requires.txt +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/top_level.txt +0 -0
- {clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clouditia-manager
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Manage GPU sessions on Clouditia platform
|
|
5
5
|
Home-page: https://clouditia.com
|
|
6
6
|
Author: Aina KIKI-SAGBE
|
|
@@ -191,7 +191,47 @@ print(f"GPU Count: {session.gpu_count}") # 2
|
|
|
191
191
|
print(f"GPUs: {session.gpus}") # Liste des configs GPU
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
### 4.
|
|
194
|
+
### 4. Gestion de la disponibilité GPU (allow_partial)
|
|
195
|
+
|
|
196
|
+
Le SDK vérifie automatiquement la disponibilité des GPUs demandés avant de créer la session.
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# Si certains GPUs ne sont pas disponibles, le SDK affiche:
|
|
200
|
+
# ==================================================
|
|
201
|
+
# GPU AVAILABILITY CHECK
|
|
202
|
+
# ==================================================
|
|
203
|
+
# Unavailable GPUs:
|
|
204
|
+
# - nvidia-rtx-4090
|
|
205
|
+
# Available GPUs:
|
|
206
|
+
# - nvidia-rtx-3090
|
|
207
|
+
# ==================================================
|
|
208
|
+
# Continue with 1 available GPU(s)? [y/N]:
|
|
209
|
+
|
|
210
|
+
# Mode interactif (par défaut): demande confirmation
|
|
211
|
+
session = manager.create_session(
|
|
212
|
+
gpus=[
|
|
213
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
214
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
215
|
+
],
|
|
216
|
+
vcpu=4,
|
|
217
|
+
ram=16,
|
|
218
|
+
storage=20
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Mode automatique: continue avec les GPUs disponibles
|
|
222
|
+
session = manager.create_session(
|
|
223
|
+
gpus=[
|
|
224
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
225
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
226
|
+
],
|
|
227
|
+
vcpu=4,
|
|
228
|
+
ram=16,
|
|
229
|
+
storage=20,
|
|
230
|
+
allow_partial=True # Continue avec les GPUs disponibles uniquement
|
|
231
|
+
)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 5. Lister les sessions
|
|
195
235
|
|
|
196
236
|
```python
|
|
197
237
|
# Toutes les sessions
|
|
@@ -264,14 +304,17 @@ session = manager.stop_session(
|
|
|
264
304
|
session = manager.stop_session("0e4c713a", wait_stopped=False, verbose=False)
|
|
265
305
|
```
|
|
266
306
|
|
|
267
|
-
### 8. Consulter
|
|
307
|
+
### 8. Consulter les GPUs disponibles
|
|
268
308
|
|
|
269
309
|
```python
|
|
270
310
|
inventory = manager.get_inventory()
|
|
271
311
|
|
|
272
|
-
|
|
273
|
-
print(
|
|
274
|
-
|
|
312
|
+
if not inventory:
|
|
313
|
+
print("Aucun GPU disponible actuellement")
|
|
314
|
+
else:
|
|
315
|
+
for gpu in inventory:
|
|
316
|
+
print(f"{gpu.gpu_name}: {gpu.available} disponible(s)")
|
|
317
|
+
print(f" Prix: {gpu.price_per_hour}EUR/h")
|
|
275
318
|
```
|
|
276
319
|
|
|
277
320
|
### 9. Générer une clé SDK (sk_live_)
|
|
@@ -356,9 +399,7 @@ except APIError as e:
|
|
|
356
399
|
|----------|------|-------------|
|
|
357
400
|
| `gpu_type` | str | Slug du GPU |
|
|
358
401
|
| `gpu_name` | str | Nom complet du GPU |
|
|
359
|
-
| `
|
|
360
|
-
| `available` | int | Stock disponible |
|
|
361
|
-
| `in_use` | int | Stock en utilisation |
|
|
402
|
+
| `available` | int | Nombre de GPUs disponibles |
|
|
362
403
|
| `price_per_hour` | float | Prix par heure (EUR) |
|
|
363
404
|
|
|
364
405
|
## License
|
|
@@ -149,7 +149,47 @@ print(f"GPU Count: {session.gpu_count}") # 2
|
|
|
149
149
|
print(f"GPUs: {session.gpus}") # Liste des configs GPU
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
-
### 4.
|
|
152
|
+
### 4. Gestion de la disponibilité GPU (allow_partial)
|
|
153
|
+
|
|
154
|
+
Le SDK vérifie automatiquement la disponibilité des GPUs demandés avant de créer la session.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Si certains GPUs ne sont pas disponibles, le SDK affiche:
|
|
158
|
+
# ==================================================
|
|
159
|
+
# GPU AVAILABILITY CHECK
|
|
160
|
+
# ==================================================
|
|
161
|
+
# Unavailable GPUs:
|
|
162
|
+
# - nvidia-rtx-4090
|
|
163
|
+
# Available GPUs:
|
|
164
|
+
# - nvidia-rtx-3090
|
|
165
|
+
# ==================================================
|
|
166
|
+
# Continue with 1 available GPU(s)? [y/N]:
|
|
167
|
+
|
|
168
|
+
# Mode interactif (par défaut): demande confirmation
|
|
169
|
+
session = manager.create_session(
|
|
170
|
+
gpus=[
|
|
171
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
172
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
173
|
+
],
|
|
174
|
+
vcpu=4,
|
|
175
|
+
ram=16,
|
|
176
|
+
storage=20
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Mode automatique: continue avec les GPUs disponibles
|
|
180
|
+
session = manager.create_session(
|
|
181
|
+
gpus=[
|
|
182
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
183
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
184
|
+
],
|
|
185
|
+
vcpu=4,
|
|
186
|
+
ram=16,
|
|
187
|
+
storage=20,
|
|
188
|
+
allow_partial=True # Continue avec les GPUs disponibles uniquement
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 5. Lister les sessions
|
|
153
193
|
|
|
154
194
|
```python
|
|
155
195
|
# Toutes les sessions
|
|
@@ -222,14 +262,17 @@ session = manager.stop_session(
|
|
|
222
262
|
session = manager.stop_session("0e4c713a", wait_stopped=False, verbose=False)
|
|
223
263
|
```
|
|
224
264
|
|
|
225
|
-
### 8. Consulter
|
|
265
|
+
### 8. Consulter les GPUs disponibles
|
|
226
266
|
|
|
227
267
|
```python
|
|
228
268
|
inventory = manager.get_inventory()
|
|
229
269
|
|
|
230
|
-
|
|
231
|
-
print(
|
|
232
|
-
|
|
270
|
+
if not inventory:
|
|
271
|
+
print("Aucun GPU disponible actuellement")
|
|
272
|
+
else:
|
|
273
|
+
for gpu in inventory:
|
|
274
|
+
print(f"{gpu.gpu_name}: {gpu.available} disponible(s)")
|
|
275
|
+
print(f" Prix: {gpu.price_per_hour}EUR/h")
|
|
233
276
|
```
|
|
234
277
|
|
|
235
278
|
### 9. Générer une clé SDK (sk_live_)
|
|
@@ -314,9 +357,7 @@ except APIError as e:
|
|
|
314
357
|
|----------|------|-------------|
|
|
315
358
|
| `gpu_type` | str | Slug du GPU |
|
|
316
359
|
| `gpu_name` | str | Nom complet du GPU |
|
|
317
|
-
| `
|
|
318
|
-
| `available` | int | Stock disponible |
|
|
319
|
-
| `in_use` | int | Stock en utilisation |
|
|
360
|
+
| `available` | int | Nombre de GPUs disponibles |
|
|
320
361
|
| `price_per_hour` | float | Prix par heure (EUR) |
|
|
321
362
|
|
|
322
363
|
## License
|
|
@@ -46,16 +46,14 @@ class GPUSession:
|
|
|
46
46
|
|
|
47
47
|
@dataclass
|
|
48
48
|
class GPUInventory:
|
|
49
|
-
"""Represents GPU
|
|
49
|
+
"""Represents available GPU in marketplace"""
|
|
50
50
|
gpu_type: str
|
|
51
51
|
gpu_name: str
|
|
52
|
-
total: int
|
|
53
52
|
available: int
|
|
54
|
-
in_use: int
|
|
55
53
|
price_per_hour: float
|
|
56
54
|
|
|
57
55
|
def __repr__(self):
|
|
58
|
-
return f"GPUInventory(type='{self.gpu_type}', available={self.available}
|
|
56
|
+
return f"GPUInventory(type='{self.gpu_type}', available={self.available})"
|
|
59
57
|
|
|
60
58
|
|
|
61
59
|
class GPUManager:
|
|
@@ -129,6 +127,12 @@ class GPUManager:
|
|
|
129
127
|
raise AuthenticationError("Access denied")
|
|
130
128
|
elif response.status_code == 404:
|
|
131
129
|
raise SessionNotFoundError("Resource not found")
|
|
130
|
+
elif response.status_code == 400:
|
|
131
|
+
# Return JSON response for 400 errors (may contain availability info)
|
|
132
|
+
try:
|
|
133
|
+
return response.json()
|
|
134
|
+
except:
|
|
135
|
+
raise APIError(f"Bad request: {response.text}")
|
|
132
136
|
|
|
133
137
|
response.raise_for_status()
|
|
134
138
|
return response.json()
|
|
@@ -148,7 +152,8 @@ class GPUManager:
|
|
|
148
152
|
storage: int = 20,
|
|
149
153
|
wait_ready: bool = True,
|
|
150
154
|
timeout: int = 180,
|
|
151
|
-
verbose: bool = True
|
|
155
|
+
verbose: bool = True,
|
|
156
|
+
allow_partial: bool = False
|
|
152
157
|
) -> GPUSession:
|
|
153
158
|
"""
|
|
154
159
|
Create a new GPU session.
|
|
@@ -165,6 +170,8 @@ class GPUManager:
|
|
|
165
170
|
wait_ready: Wait for session to be fully ready (default: True)
|
|
166
171
|
timeout: Max wait time in seconds (default: 180)
|
|
167
172
|
verbose: Print status messages (default: True)
|
|
173
|
+
allow_partial: If True, create session with only available GPUs
|
|
174
|
+
when some requested GPUs are unavailable (default: False)
|
|
168
175
|
|
|
169
176
|
Returns:
|
|
170
177
|
GPUSession object with session details
|
|
@@ -177,7 +184,8 @@ class GPUManager:
|
|
|
177
184
|
data = {
|
|
178
185
|
"vcpu": vcpu,
|
|
179
186
|
"ram": ram,
|
|
180
|
-
"storage": storage
|
|
187
|
+
"storage": storage,
|
|
188
|
+
"allow_partial": allow_partial
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
# Support both single GPU and multiple GPUs
|
|
@@ -192,11 +200,67 @@ class GPUManager:
|
|
|
192
200
|
|
|
193
201
|
if verbose:
|
|
194
202
|
print(f"Creating GPU session with {gpu_desc}...")
|
|
203
|
+
print(f"Checking GPU availability...")
|
|
195
204
|
|
|
196
205
|
response = self._request("POST", "/api/computing/sessions/create/", data=data)
|
|
197
206
|
|
|
207
|
+
# Handle partial availability response
|
|
198
208
|
if not response.get("success"):
|
|
199
209
|
error = response.get("error", "Unknown error")
|
|
210
|
+
unavailable = response.get("unavailable_gpus", [])
|
|
211
|
+
available = response.get("available_gpus", [])
|
|
212
|
+
|
|
213
|
+
# Check if this is a partial availability situation
|
|
214
|
+
if unavailable and available:
|
|
215
|
+
if verbose:
|
|
216
|
+
print(f"\n{'='*50}")
|
|
217
|
+
print(f" GPU AVAILABILITY CHECK")
|
|
218
|
+
print(f"{'='*50}")
|
|
219
|
+
print(f" Unavailable GPUs:")
|
|
220
|
+
for gpu in unavailable:
|
|
221
|
+
print(f" - {gpu}")
|
|
222
|
+
print(f" Available GPUs:")
|
|
223
|
+
for gpu in available:
|
|
224
|
+
print(f" - {gpu}")
|
|
225
|
+
print(f"{'='*50}")
|
|
226
|
+
|
|
227
|
+
# Ask user if they want to continue with available GPUs
|
|
228
|
+
try:
|
|
229
|
+
user_input = input(f"\nContinue with {len(available)} available GPU(s)? [y/N]: ").strip().lower()
|
|
230
|
+
if user_input in ['y', 'yes', 'o', 'oui']:
|
|
231
|
+
# Retry with allow_partial=True
|
|
232
|
+
data["allow_partial"] = True
|
|
233
|
+
if verbose:
|
|
234
|
+
print(f"\nCreating session with available GPUs only...")
|
|
235
|
+
response = self._request("POST", "/api/computing/sessions/create/", data=data)
|
|
236
|
+
|
|
237
|
+
if not response.get("success"):
|
|
238
|
+
raise APIError(response.get("error", "Failed to create session"))
|
|
239
|
+
else:
|
|
240
|
+
raise InsufficientResourcesError(
|
|
241
|
+
f"GPUs indisponibles: {', '.join(unavailable)}"
|
|
242
|
+
)
|
|
243
|
+
except EOFError:
|
|
244
|
+
# Non-interactive mode, raise error
|
|
245
|
+
raise InsufficientResourcesError(
|
|
246
|
+
f"GPUs indisponibles: {', '.join(unavailable)}. "
|
|
247
|
+
f"Utilisez allow_partial=True pour continuer avec: {', '.join(available)}"
|
|
248
|
+
)
|
|
249
|
+
else:
|
|
250
|
+
# Not verbose, just raise error with info
|
|
251
|
+
raise InsufficientResourcesError(
|
|
252
|
+
f"GPUs indisponibles: {', '.join(unavailable)}. "
|
|
253
|
+
f"GPUs disponibles: {', '.join(available)}. "
|
|
254
|
+
f"Utilisez allow_partial=True pour continuer."
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# No GPUs available at all
|
|
258
|
+
elif unavailable and not available:
|
|
259
|
+
raise InsufficientResourcesError(
|
|
260
|
+
f"Aucun GPU disponible. Indisponibles: {', '.join(unavailable)}"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# Other error
|
|
200
264
|
if "disponible" in error.lower() or "available" in error.lower():
|
|
201
265
|
raise InsufficientResourcesError(error)
|
|
202
266
|
raise APIError(error)
|
|
@@ -464,7 +528,8 @@ class GPUManager:
|
|
|
464
528
|
Get available GPU inventory.
|
|
465
529
|
|
|
466
530
|
Returns:
|
|
467
|
-
List of GPUInventory objects
|
|
531
|
+
List of GPUInventory objects (only GPUs with available stock)
|
|
532
|
+
Empty list if no GPUs are available
|
|
468
533
|
"""
|
|
469
534
|
response = self._request("GET", "/api/computing/inventory/")
|
|
470
535
|
|
|
@@ -473,9 +538,7 @@ class GPUManager:
|
|
|
473
538
|
inventory.append(GPUInventory(
|
|
474
539
|
gpu_type=item.get("gpu_type", ""),
|
|
475
540
|
gpu_name=item.get("gpu_name", ""),
|
|
476
|
-
total=item.get("total", 0),
|
|
477
541
|
available=item.get("available", 0),
|
|
478
|
-
in_use=item.get("in_use", 0),
|
|
479
542
|
price_per_hour=item.get("price_per_hour", 0.0)
|
|
480
543
|
))
|
|
481
544
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clouditia-manager
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Manage GPU sessions on Clouditia platform
|
|
5
5
|
Home-page: https://clouditia.com
|
|
6
6
|
Author: Aina KIKI-SAGBE
|
|
@@ -191,7 +191,47 @@ print(f"GPU Count: {session.gpu_count}") # 2
|
|
|
191
191
|
print(f"GPUs: {session.gpus}") # Liste des configs GPU
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
### 4.
|
|
194
|
+
### 4. Gestion de la disponibilité GPU (allow_partial)
|
|
195
|
+
|
|
196
|
+
Le SDK vérifie automatiquement la disponibilité des GPUs demandés avant de créer la session.
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# Si certains GPUs ne sont pas disponibles, le SDK affiche:
|
|
200
|
+
# ==================================================
|
|
201
|
+
# GPU AVAILABILITY CHECK
|
|
202
|
+
# ==================================================
|
|
203
|
+
# Unavailable GPUs:
|
|
204
|
+
# - nvidia-rtx-4090
|
|
205
|
+
# Available GPUs:
|
|
206
|
+
# - nvidia-rtx-3090
|
|
207
|
+
# ==================================================
|
|
208
|
+
# Continue with 1 available GPU(s)? [y/N]:
|
|
209
|
+
|
|
210
|
+
# Mode interactif (par défaut): demande confirmation
|
|
211
|
+
session = manager.create_session(
|
|
212
|
+
gpus=[
|
|
213
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
214
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
215
|
+
],
|
|
216
|
+
vcpu=4,
|
|
217
|
+
ram=16,
|
|
218
|
+
storage=20
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Mode automatique: continue avec les GPUs disponibles
|
|
222
|
+
session = manager.create_session(
|
|
223
|
+
gpus=[
|
|
224
|
+
{'type': 'nvidia-rtx-3090', 'count': 1},
|
|
225
|
+
{'type': 'nvidia-rtx-4090', 'count': 1}
|
|
226
|
+
],
|
|
227
|
+
vcpu=4,
|
|
228
|
+
ram=16,
|
|
229
|
+
storage=20,
|
|
230
|
+
allow_partial=True # Continue avec les GPUs disponibles uniquement
|
|
231
|
+
)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 5. Lister les sessions
|
|
195
235
|
|
|
196
236
|
```python
|
|
197
237
|
# Toutes les sessions
|
|
@@ -264,14 +304,17 @@ session = manager.stop_session(
|
|
|
264
304
|
session = manager.stop_session("0e4c713a", wait_stopped=False, verbose=False)
|
|
265
305
|
```
|
|
266
306
|
|
|
267
|
-
### 8. Consulter
|
|
307
|
+
### 8. Consulter les GPUs disponibles
|
|
268
308
|
|
|
269
309
|
```python
|
|
270
310
|
inventory = manager.get_inventory()
|
|
271
311
|
|
|
272
|
-
|
|
273
|
-
print(
|
|
274
|
-
|
|
312
|
+
if not inventory:
|
|
313
|
+
print("Aucun GPU disponible actuellement")
|
|
314
|
+
else:
|
|
315
|
+
for gpu in inventory:
|
|
316
|
+
print(f"{gpu.gpu_name}: {gpu.available} disponible(s)")
|
|
317
|
+
print(f" Prix: {gpu.price_per_hour}EUR/h")
|
|
275
318
|
```
|
|
276
319
|
|
|
277
320
|
### 9. Générer une clé SDK (sk_live_)
|
|
@@ -356,9 +399,7 @@ except APIError as e:
|
|
|
356
399
|
|----------|------|-------------|
|
|
357
400
|
| `gpu_type` | str | Slug du GPU |
|
|
358
401
|
| `gpu_name` | str | Nom complet du GPU |
|
|
359
|
-
| `
|
|
360
|
-
| `available` | int | Stock disponible |
|
|
361
|
-
| `in_use` | int | Stock en utilisation |
|
|
402
|
+
| `available` | int | Nombre de GPUs disponibles |
|
|
362
403
|
| `price_per_hour` | float | Prix par heure (EUR) |
|
|
363
404
|
|
|
364
405
|
## License
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{clouditia_manager-1.2.2 → clouditia_manager-1.3.2}/clouditia_manager.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|