Checking the Progress of the Backup Copy of the Clone Resynchronization

Here is a script to verify that the background copy of the Clone resynchronization is complete. This script is used in the operation to create a regular full backup using QuickOPC. For more information, see the description of Creating Regular Full Backups with QuickOPC.

Once the start of resynchronization (quickopc_resync.py) is complete, access to the business volume can be resumed, but data is being copied in the background. Therefore, you cannot restore from a Clone until the background copy is complete. If you want to verify that the resynchronization is complete, use the script described here.

The sequence of script processing is as follows.

  1. Use the GET /volume/copysession/ API to check the progress of the background copy and wait for the copy to complete.

quickopc_wait_sync.py


import time
import sys

from eternus_rest import EtdxBaseApi

# Change the following values for your environment.
storage_url = "https://192.168.0.1:5665"
storage_user_name = "username"
storage_password = "password"

# Change the following values as required.
# Specify the list of clone pairs. A clone pair is a tuple with a source
# volume ID and a clone volume ID of a QuickOPC.
# If you want to wait for the synchronization of multiple QuickOPCs to
# complete, list the clone pairs.
# Examples:
# clone_pair_list = [(100001,1100001),(200001,1200001)]
# This is specified to check the following QuickOPCs.
# QuickOPC#0 (source volume ID 100001, clone volume ID 1100001)
# QuickOPC#1 (source volume ID 200001, clone volume ID 1200001)
clone_pair_list = [(100001, 1100001), (200001, 1200001)]

# If you want to schedule this script, you can use cron as follows.
# Examples: It is scheduled daily at 20:00.
# crontab -e
# 0 20 * * * python3 /root/quickopc_resync.py >> /root/cron.log 2>&1


class EtdxApi(EtdxBaseApi):
    def __init__(self, base_url, boxid=None, proxies=None):
        super().__init__(base_url, boxid=boxid, proxies=proxies)

    def quickopc_wait_for_sync_completion(self, clone_volume_id_list):
        """Wait for all the QuickOPC clones synchronization to complete.

        Args:
            clone_volume_id_list (list[int]): List of clone volume IDs of
              QuickOPCs to check.

        Returns:
            bool: True if synchronization of all the specified QuickOPC clones
              are complete. False otherwise. Returns false if retrieving
              clone information failed.
        """
        while True:
            r = super().get("/api/v1/volume/copysession?volume_id={}"
                            "&fields=status,phase"
                            .format(",".join(map(str, clone_volume_id_list))))
            data = r.json()
            if r.status_code != 200 or data["list_count"] == 0:
                print("Failed to get information of clones.")
                print(r)
                print(data)
                return False
            try:
                status_list = [i["status"] for i in data["volume_list"]]
                phase_list = [i["phase"] for i in data["volume_list"]]
            except Exception:
                print("Some volumes are not clones.")
                print(data)
                return False
            # Returns false if not all of the specified clones are in
            # "Active" status.
            if status_list.count("Active") != len(clone_volume_id_list):
                print("Failed to get information about some clones or some "
                      "clones have an error.")
                print(data)
                return False
            # Break if all of the specified clones are in "Tracking" phase.
            if len(phase_list) == phase_list.count("Tracking"):
                break
            time.sleep(5 * 60)
        return True


def main():
    storage = EtdxApi(storage_url)

    # Login
    if not storage.login(storage_user_name, storage_password):
        return False

    print("Waiting for completion of sync of QuickOPC clones.")
    print("Clone pair list to check:", clone_pair_list)

    # Wait for completion of sync of clones
    clone_volume_id_list = [i[1] for i in clone_pair_list]
    if not storage.quickopc_wait_for_sync_completion(clone_volume_id_list):
        print("Failed to wait for completion of sync of the clones.")
        return False
    print("Completed to synchronize clones.")

    # Get information of all the specified clones.
    for backup_volume_id in clone_volume_id_list:
        r = storage.get("/api/v1/volume/{0!s}/copysession"
                        .format(backup_volume_id))
        print(r)
        print(r.json())

    # Logout
    storage.logout()
    return True


if __name__ == '__main__':
    if not main():
        sys.exit(1)