リモート筐体のバックアップVolumeへのデータ転送の再開

業務終了後(業務Volumeへのアクセス終了後)に、リモート筐体へのデータ転送を再開するスクリプトを記載します。このスクリプトは、非同期StackモードのRECとQuickOPCを使用して、リモート筐体に業務Volumeのバックアップを定期的に作成する運用で使用します。詳細は、RECとQuickOPCを使用したリモート筐体へのバックアップの作成を参照してください。

スクリプトの処理の流れは以下です。

  1. POST /copysession/{copysession_id}/resume APIを使用し、REC Sessionを再開する。

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)