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

