aipmodel 0.2.71__tar.gz → 0.2.72__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aipmodel
3
- Version: 0.2.71
3
+ Version: 0.2.72
4
4
  Summary: SDK for model registration, versioning, and storage
5
5
  Home-page: https://github.com/AIP-MLOPS/model-registry
6
6
  Author: AIP MLOPS Team
@@ -120,6 +120,71 @@ reset). The SDK now **retries these automatically**, so `add_model`,
120
120
  worker) is fully protected; for multiple workers/replicas add a distributed
121
121
  lock (Mlops-Core/Redis).
122
122
 
123
+ ## Registry ↔ Storage Consistency (Integrity, Repair & Disaster Recovery)
124
+
125
+ A model lives in **two systems at once**: its metadata in the registry
126
+ (Mlops-Core) and its files in S3/Ceph. If either side changes behind the SDK's
127
+ back (someone deletes a folder in Ceph by hand, or the registry loses data),
128
+ you get a **zombie** (registry entry pointing at missing files) or an
129
+ **orphan** (files no registry entry references). The SDK detects, repairs, and
130
+ recovers all of these:
131
+
132
+ ### Recovery sidecar: `_meta.json`
133
+
134
+ Every `add_model` writes a small `_meta.json` next to each version's files
135
+ (model name, version, number, category, tags, owner, size, created, public).
136
+ Storage is therefore **self-describing** — a registry entry can be rebuilt from
137
+ S3 alone.
138
+
139
+ ### Detect
140
+
141
+ ```python
142
+ report = manager.verify_model_integrity(model_name="my_model")
143
+ # {"status": "ok" | "missing_files" | "orphan_files",
144
+ # "versions": [{"version": "v1.0", "files_exist": True, ...}],
145
+ # "orphan_folders": [...]}
146
+
147
+ manager.verify_all_models() # one report per model in your project
148
+ manager.find_orphan_models() # S3 model folders unknown to the registry
149
+ # (each flagged recoverable=True when _meta.json exists)
150
+ ```
151
+
152
+ ### Repair (each guarded against misuse)
153
+
154
+ ```python
155
+ # Zombie version (files deleted in Ceph) -> remove it from the registry.
156
+ # REFUSES if the files actually still exist (use delete_model for a real delete).
157
+ manager.remove_missing_version("my_model", "v1.0")
158
+
159
+ # Stray folders under a model that no version references -> delete them.
160
+ manager.purge_orphan_folders(model_name="my_model")
161
+
162
+ # S3 model folder the registry doesn't know -> delete it.
163
+ # REFUSES if the id IS registered.
164
+ manager.purge_orphan_model(model_id)
165
+ ```
166
+
167
+ ### Disaster recovery (registry data lost, S3 survives)
168
+
169
+ ```python
170
+ for orphan in manager.find_orphan_models():
171
+ if orphan["recoverable"]:
172
+ manager.recover_model_from_storage(orphan["model_id"])
173
+ # Rebuilds the registry entry (name, all versions, latest, sizes, category,
174
+ # tags) from the _meta.json sidecars. Files stay where they are.
175
+ ```
176
+
177
+ Consistency is also protected *proactively*: `add_model` rolls back files,
178
+ registry entry and ACL record together on failure, and `delete_model` updates
179
+ the registry **before** deleting S3 (a crash can leave a harmless orphan, never
180
+ a zombie). Versions added before the sidecar feature (< 0.2.69) have no
181
+ `_meta.json` and are reported as non-recoverable.
182
+
183
+ > **S3-compat note:** the client is configured to stay compatible with
184
+ > MinIO/Ceph RGW across boto3 versions (legacy `Content-MD5` checksums on
185
+ > newer boto3, with a per-object delete fallback if a batch delete is
186
+ > rejected) — no user action needed.
187
+
123
188
  ## Access Control (ACL)
124
189
 
125
190
  ACL is **off by default** and fully optional. Toggle it with one env var:
@@ -314,7 +379,32 @@ manager.delete_model(model_name="demo_model_hf")
314
379
  | **`set_latest_version`** | `model_name`, `version` | Updates the 'latest' pointer to a specific version without modifying files. |
315
380
  | **`set_model_public`** | `model_name`, `public` | Moves a model's files between the private and public buckets (transactional, parallel server-side copy). |
316
381
  | **`share_model`** | `model_name`, `target_user`, `access_level` | Grants another user access to a model. Requires `ACL_ENABLED=true`. |
317
- | **`delete_model`** | `model_name`, `version` | If `version` provided: deletes that version (and rolls "latest" back to the next one if it was the latest). If that was the *last* version, the model container is removed too. If `version` is omitted: deletes the entire model in one call — this already is "delete all versions", no need to delete one by one. |
382
+ | **`delete_model`** | `model_name`, `version` | If `version` provided: deletes that version (and rolls "latest" back to the next one if it was the latest). If that was the *last* version, the model container is removed too. If `version` is omitted: deletes the entire model in one call — this already is "delete all versions", no need to delete one by one. Registry metadata is updated **before** S3 files are removed (crash-safe ordering). |
383
+ | **`verify_model_integrity`** | `model_name` or `model_id` | Cross-checks one model between registry and S3. Returns `{status: ok\|missing_files\|orphan_files, versions: [...], orphan_folders: [...]}`. |
384
+ | **`verify_all_models`** | — | Runs `verify_model_integrity` over every model in your project; returns a list of reports. |
385
+ | **`find_orphan_models`** | — | Lists S3 model folders the registry doesn't know about, each flagged `recoverable` when a `_meta.json` sidecar exists. |
386
+ | **`remove_missing_version`** | `model_name`, `version` | Sync-repair for a zombie version whose S3 files were deleted: removes it from the registry. Refuses if the files still exist. |
387
+ | **`purge_orphan_folders`** | `model_name` or `model_id` | Deletes S3 folders under a model that no registry version references. Returns the purged folder names. |
388
+ | **`purge_orphan_model`** | `model_id` | Deletes the S3 storage of a model unknown to the registry. Refuses for registered ids. |
389
+ | **`recover_model_from_storage`** | `model_id` | Disaster recovery: rebuilds the registry entry (all versions, latest, category, tags) from the `_meta.json` sidecars in S3. Returns the new registry id. |
390
+
391
+ ### Backward compatibility
392
+
393
+ The ClearML → Mlops-Core rename kept the old public names working, so code
394
+ written against the pre-0.2.65 SDK does not break:
395
+
396
+ - **Health-check methods** — `check_clearml_service()` and `check_clearml_auth()`
397
+ still exist as thin aliases of `check_mlops_core_service()` /
398
+ `check_mlops_core_auth()`.
399
+ - **Instance attributes** — `mgr.CLEARML_API_HOST`, `CLEARML_WEB_HOST`,
400
+ `CLEARML_USERNAME`, `CLEARML_ACCESS_KEY`, `CLEARML_SECRET_KEY` are kept as
401
+ aliases of the canonical `MLOPS_CORE_*` attributes.
402
+ - **Constructor / env** — the `CLEARML_API_HOST` / `CLEARML_WEB_HOST` kwargs and
403
+ env vars are accepted as deprecated fallbacks (the `MLOPS_CORE_*` names win if
404
+ both are set).
405
+ - **Method signatures are additive only** — every new parameter (`owner`,
406
+ `model_folder_name`, the `list_models` filters) is optional with a default
407
+ that reproduces the old behavior; nothing was removed or reordered.
318
408
 
319
409
  ---
320
410
 
@@ -11,5 +11,5 @@ if _os.environ.get("AIPMODEL_UPDATE_CHECK", "").lower() in ("1", "true", "yes"):
11
11
 
12
12
  __all__ = ["MLOpsManager", "CephS3Manager"]
13
13
 
14
- __version__ = "0.2.71"
14
+ __version__ = "0.2.72"
15
15
  __description__ = "SDK for model registration, versioning, and storage"
@@ -434,7 +434,17 @@ class MLOpsManager:
434
434
  # from the user-management wire format — do not rename them.
435
435
  self.MLOPS_CORE_ACCESS_KEY = user_info["clearml_access_key"]
436
436
  self.MLOPS_CORE_SECRET_KEY = user_info["clearml_secret_key"]
437
-
437
+
438
+ # Backward-compatibility attribute aliases (pre-0.2.65 names). Callers
439
+ # that read mgr.CLEARML_API_HOST / CLEARML_WEB_HOST / CLEARML_USERNAME /
440
+ # CLEARML_ACCESS_KEY / CLEARML_SECRET_KEY keep working after the
441
+ # Mlops-Core rename — the new MLOPS_CORE_* names are canonical.
442
+ self.CLEARML_API_HOST = self.MLOPS_CORE_API_HOST
443
+ self.CLEARML_WEB_HOST = self.MLOPS_CORE_WEB_HOST
444
+ self.CLEARML_USERNAME = self.MLOPS_CORE_USERNAME
445
+ self.CLEARML_ACCESS_KEY = self.MLOPS_CORE_ACCESS_KEY
446
+ self.CLEARML_SECRET_KEY = self.MLOPS_CORE_SECRET_KEY
447
+
438
448
  if not skip_connection_check:
439
449
  if self.verbose:
440
450
  print("[SDK_INFO] Performing health checks...")
@@ -608,6 +618,16 @@ class MLOpsManager:
608
618
  print(f"[SDK_FAIL] Mlops-Core Auth Check Failed: {e}")
609
619
  return False
610
620
 
621
+ # Backward-compatibility aliases. These methods were renamed
622
+ # check_clearml_* -> check_mlops_core_* as part of the Mlops-Core rename;
623
+ # the old names are kept as thin forwarders so pre-0.2.65 callers that do
624
+ # mgr.check_clearml_service() / mgr.check_clearml_auth() keep working.
625
+ def check_clearml_service(self):
626
+ return self.check_mlops_core_service()
627
+
628
+ def check_clearml_auth(self):
629
+ return self.check_mlops_core_auth()
630
+
611
631
  def get_model_id_by_name(self, name, owner=None):
612
632
  """
613
633
  Resolves a model name to its Mlops-Core ID.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aipmodel
3
- Version: 0.2.71
3
+ Version: 0.2.72
4
4
  Summary: SDK for model registration, versioning, and storage
5
5
  Home-page: https://github.com/AIP-MLOPS/model-registry
6
6
  Author: AIP MLOPS Team
@@ -31,7 +31,7 @@ version, description = read_meta()
31
31
 
32
32
  setup(
33
33
  name="aipmodel",
34
- version="0.2.71",
34
+ version="0.2.72",
35
35
  description=description,
36
36
  author="AIP MLOPS Team",
37
37
  author_email="mohmmadweb@gmail.com",
File without changes
File without changes
File without changes