→ Applies to: SynetoOS 6.x
After upgrading from SynetoOS 5 to SynetoOS 6, some or all previously configured SLA policies may no longer be visible. For example, in the screenshot below the Platinum SLA policy is missing after upgrading to SynetoOS 6. Follow the steps below to resolve this issue.
Step 1. Connect to SynetoOS appliance via SSH as admin
ssh admin@<your_ip_address_or_hostname>
Step 2. Get root privileges
sudo su -
Step 3. Create “/tmp/slapolicy_assignments_os6.py” file
vi /tmp/slapolicy_assignments_os6.py
IMPORTANT
Make sure to copy and paste the exact lines below.#!/usr/share/syneto-giove/.venv/bin/python from typing import Optional import signal import sys import getpass from syneto_api import Authentication, V1Protection, V1Jobs, Storage def signal_handler(signum, frame): """Handle Ctrl-C gracefully with exit code 130""" print("\nInterrupted by user (Ctrl-C)") sys.exit(130) def get_policy_by_id(id: str, policies: list[dict]) -> Optional[dict]: if not id: raise ValueError("Policy id cannot be empty") for policy in policies: if policy.get("id") == id: return policy return None def get_storage_volume_by_id(id: str, volumes: list[dict]) -> Optional[dict]: if not id: raise ValueError("Volume id cannot be empty") for volume in volumes: if volume.get("id") == id: return volume return None def delete_policy_assignments(assignments: list[dict], protection_api: V1Protection, jobs_api: V1Jobs): delete_job_ids = {} for assignment in assignments: assignment_id = assignment.get("id") if not assignment_id: print(f"Error: Failed to delete policy assignment with invalid id={assignment_id}") continue delete_response = protection_api.delete_policy_assignment(assignment_id) delete_job_id = delete_response.get("jobId") if not delete_job_id: print(f"Error: Failed to delete policy assignment id={assignment_id}, could not retrieve deletion job id") continue delete_job_ids[delete_job_id] = assignment_id failed_delete_job_ids = {} for job_id in delete_job_ids: try: job_response = jobs_api.wait_for_job_completion(job_id, timeout=10) if job_response.get("status") != "SUCCEEDED": failed_delete_job_ids[job_id] = delete_job_ids[job_id] except Exception as e: print(f"Error: failed to wait for completion of job id={job_id}: {repr(e)}") failed_delete_job_ids[job_id] = delete_job_ids[job_id] if failed_delete_job_ids: print("Error: Failed to delete the following policy assignments:") for job_id in failed_delete_job_ids: print(f" - policyAssignmentId={failed_delete_job_ids[job_id]} (jobId={job_id})") print(f"Deleted {len(delete_job_ids) - len(failed_delete_job_ids)} of {len(delete_job_ids)} policy assignments") def main(): password = getpass.getpass("Enter support password: ") print() auth = Authentication(url_base="https://localhost/api/auth", insecure_ssl=True) auth_response = auth.login(username="support", password=password) jwt = auth_response["jwt"] protection_api = V1Protection(url_base="https://localhost/api/protection", insecure_ssl=True) protection_api.set_auth_jwt(jwt) storage_api = Storage(url_base="https://localhost/api/storage", insecure_ssl=True) storage_api.set_auth_jwt(jwt) jobs_api = V1Jobs(url_base="https://localhost/api/protection", insecure_ssl=True) jobs_api.set_auth_jwt(jwt) assignments = protection_api.get_policy_assignments() policies = protection_api.get_policies() volumes = storage_api.get_volumes() assignments_to_delete = [] for assignment in assignments: assignment_id = assignment.get("id") storage_volume_id = assignment.get("storageVolumeId") if not storage_volume_id: print( f"Warning: Policy assignment id={assignment_id} has invalid storageVolumeId={storage_volume_id}, skipping" ) continue policy_id = assignment.get("policyId") if not policy_id: print(f"Warning: Policy assignment id={assignment_id} has invalid policyId={policy_id}, skipping") continue policy = get_policy_by_id(policy_id, policies) if not policy: print(f"Warning: Policy id={policy_id} for assignment id={assignment_id} not found, skipping") continue if not policy.get("origin"): continue # Not a replicated policy, skip # We now have a replicated policy storage_volume = get_storage_volume_by_id(storage_volume_id, volumes) if not storage_volume: print( f"Warning: Storage volume id={storage_volume_id} for assignment id={assignment_id} not found, skipping" ) continue if storage_volume.get("replicaInfo"): continue # Correct case: replicated policy + replicated volume, skip assignments_to_delete.append(assignment) if not assignments_to_delete: print("\nFound no policy assignments to delete. Exiting.") sys.exit(0) print(f"\nFound {len(assignments_to_delete)} policy assignments to delete:\n") for assignment in assignments_to_delete: print( f" - policyAssignmentId={assignment.get('id')} policyId={assignment.get('policyId')} storageVolumeId={assignment.get('storageVolumeId')}" ) proceed = input("\nDo you want to proceed with deleting these policy assignments? (y/n): ").strip().lower() print() if proceed != "y": print("Aborted by user.") sys.exit(0) delete_policy_assignments(assignments_to_delete, protection_api=protection_api, jobs_api=jobs_api) if __name__ == "__main__": # Set up signal handler for Ctrl-C signal.signal(signal.SIGINT, signal_handler) try: main() except KeyboardInterrupt: # This should not be reached due to signal handler, but just in case print("\nInterrupted by user (Ctrl-C)") sys.exit(130)
Step 4. Make the script executable
chmod +x /tmp/slapolicy_assignments_os6.py
Step 5. Run the "slapolicy_assignments_os6.py" script
./tmp/slapolicy_assignments_os6.py