Restarting Data Transfer to a Remote Storage System Backup Volume

The following is a script to resume data transfer to the remote storage system after the end of operation (after completing access to business volumes). This script is used in the operation of periodically backing up the business volume on the remote storage system using REC in asynchronous stack mode and QuickOPC. For more information, see the description of Creating Backups to Remote Storage Systems Using REC and QuickOPC.

The sequence of script processing is as follows.

  1. Restart the REC Session using POST /copysession/{copysession_id}/resume API.

rec_stack_after_operation.py


import sys

from eternus_rest import EtdxBaseApi

# ### Change the following values for your environment. ###
# Source storage (storage that has the source volume)
storage1_url = "https://192.168.0.1:5665"
storage1_user_name = "username"
storage1_password = "password"
# Target storage (storage that has the destination volume)
storage2_url = "https://192.168.0.2:5665"
storage2_user_name = "username"
storage2_password = "password"

# This case is for a REC(Stack) session from the volume on storage1 to
# storage2.
# The destination volume of REC has been cloned using QuickOPC on storage2.
# You can paste the outputs of rec_stack_create.
# REC session ID on storage1 created by the script rec_stack_create.
storage1_copysession_id = 1

# If you want to schedule this script, you can use cron as follows.
# Examples: It is scheduled to execute this post-processing daily at 20:00.
# To ensure data consistency, host access must be stopped before execution.
# crontab -e
# 0 20 * * * python3 /root/rec_stack_after_operation.py >> /root/cron.log 2>&1


class EtdxApi(EtdxBaseApi):
    def __init__(self, base_url, boxid=None, proxies=None):
        """Constructor of EtdxApi

        If storage is used as target storage of REC without calling login
        method in this script, need to specify the boxid of this storage as
        follows.
        storage2 = EtdxApi(storage2_url,
                           boxid="00ETERNUSDXHS3ET00000A####EI000001######")

        Args:
            base_url ([type]): [description]
            boxid ([type], optional): [description]. Defaults to None.
            proxies ([type], optional): [description]. Defaults to None.
        """
        super().__init__(base_url, boxid=boxid, proxies=proxies)

    def login(self, user_name="", password=""):
        """Create a session of RESTful API and get boxid.

        Args:
            user_name (str, optional): User name to login. Defaults to "".
            password (str, optional): Password for the user. Defaults to "".

        Returns:
            bool: True if successful, False otherwise.
        """
        rtn = super().login(user_name, password)
        if rtn and self.boxid is None:
            r = super().get("/api/v1/storagesystem")
            if r.status_code != 200:
                print(r)
                print(r.json())
                print("Failed to get boxid.")
                return False
            self.boxid = r.json()["boxid"]
        return rtn

    def rec_resume(self, copysession_id):
        """Resume REC session

        Args:
            copysession_id (int): Copy session ID to resume

        Returns:
            bool: True if successful, False otherwise.
        """
        r = super().post("/api/v1/copysession/{0!s}/resume"
                         .format(copysession_id))
        if r.status_code != 202:
            print("Failed to request the REC session resume.")
            print(r)
            print(r.json())
            return False

        # Wait for the job completion
        job_r = super().wait_job(r.json()["job_id"])
        if job_r.json()["status"] != "Success":
            print("Failed to resume the REC session.")
            print(job_r)
            print(job_r.json())
            return False
        return True


def main():
    storage1 = EtdxApi(storage1_url)

    # Login
    if not storage1.login(storage1_user_name, storage1_password):
        return False

    print("Start Post-processing.")

    # Post-processing (Execute on storage1)
    # REC Resume
    print("Resuming the REC session (ID: {0!s})."
          .format(storage1_copysession_id))
    if not storage1.rec_resume(storage1_copysession_id):
        return False
    print("REC session resumed.")

    print("Post-processing completed.")

    # Logout
    storage1.logout()
    return True


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