Deleting a Copy Session

The following shows a script that removes the Copy Session.

The Copy Session can also be deleted on the DELETE /copysession/{copysession_id} API, but this API cannot be used to delete a REC Session in asynchronous consistency mode. Here is a script that determines the Copy type and automatically suspends the REC Session and then forces the deletion in asynchronous consistency mode.

Note
  • The types of Copy Sessions that can be removed with this script are OPC, QuickOPC, SnapOPC, SnapOPC+, EC, and REC.

  • Use DELETE /copysession/{copysession_id} API to force a removal of a Copy Session.

  • See the DELETE /copysession/{copysession_id} API Command Reference for considerations when removing a Copy Session.

The sequence of script processing is as follows.

  1. Use GET /copysession/{copysession_id} API to get the Copy Session information to remove.

  2. If the copy session being removed was an REC Session in asynchronous consistency mode, suspend the copy session using POST/ copysession/{copysessoin_id}/suspend API and transfer the untransferred data to the mirror volume.

  3. If the copy session being removed was an REC session in asynchronous consistency mode, use DELETE /copysession/{copysession_id} API after the data transfer is complete to force the removal of the copy session.

  4. If the copy session being removed is not a REC Session in asynchronous consistency mode, use DELETE /copysession/{copysession_id} API to remove the copy session.

copysession_delete.py


import sys
import time

from eternus_rest import EtdxBaseApi

# Change the following values for your environment.
storage1_url = "https://192.168.0.1:5665"
storage1_user_name = "username"
storage1_password = "password"

# Copy session ID to delete.
storage1_copysession_id = 1


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

    def copysession_suspend(self, copysession_id, force=False):
        """Suspend copy session

        Args:
            copysession_id (int): Copy session ID to suspend.
            force (bool, optional): True if force action is required.
              Defaults to False.

        Returns:
            bool: True if successful, False otherwise.
        """
        if force:
            r = super().post("/api/v1/copysession/{0!s}/suspend?force=true"
                             .format(copysession_id))
        else:
            r = super().post("/api/v1/copysession/{0!s}/suspend"
                             .format(copysession_id))
        if r.status_code != 202:
            print("Failed to request the copy session suspend.")
            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 suspend the copy session.")
            print(job_r)
            print(job_r.json())
            return False
        return True

    def copysession_delete(self, copysession_id, force=False):
        """Delete copy session

        Args:
            copysession_id (int): Copy session ID to delete
            force (bool, optional): True if force action is required.
              Defaults to False.

        Returns:
            bool: True if successful, False otherwise.
        """
        if force:
            r = super().delete("/api/v1/copysession/{0!s}?force=true"
                               .format(copysession_id))
        else:
            r = super().delete("/api/v1/copysession/{0!s}"
                               .format(copysession_id))
        if r.status_code != 202:
            print("Failed to request the copy session deletion.")
            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 delete the copy session.")
            print(job_r)
            print(job_r.json())
            return False
        return True

    def rec_consistency_wait_for_suspend(self, copysession_id):
        """Wait for the REC concurrent copy session to suspend.

        Args:
            copysession_id (int): Copy session ID to suspend.

        Returns:
            bool: True if suspend the copy session is completed.
              False if error occurs.
        """
        while True:
            r = super().get("/api/v1/copysession/{0!s}".format(copysession_id))
            data = r.json()
            if r.status_code != 200:
                print("Failed to get information of the copy session.")
                print(r)
                print(data)
                return False

            if data["status"] == "Error":
                print("The copy session is in error status.")
                print(data)
                return False

            if data["status"] != "Suspended":
                print("Failed to suspend the copy session. Stop access to "
                      "the source volume of the copy session and try again.")
                print(data)
                return False

            if data["concurrent_suspend_result"] == "Error":
                print("Failed to suspend the copy session.")
                print(data)
                return False

            if (data["concurrent_suspend_result"] == "Success"
                    and data["status"] == "Suspended"):
                break

            # Get it again after remain_time_to_finish_suspend.
            if data["remain_time_to_finish_suspend"] > 10:
                time.sleep(data["remain_time_to_finish_suspend"])
            else:
                time.sleep(10)

        return True

    def rec_consistency_suspend(self, copysession_id):
        """Suspend the REC consistency session

        Args:
            copysession_id (int): Copy session ID to suspend.

        Returns:
            bool: True if suspend the copy session is completed.
              False if error occurs.
        """
        # Execute suspend if the copy session is not suspended.
        r = super().get("/api/v1/copysession/{0!s}".format(copysession_id))
        data = r.json()
        if r.status_code != 200:
            print("Failed to get information of the copy session.")
            print(r)
            print(data)
            return False
        if data["status"] != "Suspended":
            # Suspend copy session
            if not self.copysession_suspend(copysession_id):
                return False

        # Wait for completion of suspend
        if not self.rec_consistency_wait_for_suspend(copysession_id):
            print("Some error occurred before suspend completion"
                  " of the copy session.")
            return False

        return True


def main():
    storage = EtdxApi(storage1_url)

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

    print("Deleting the copy session (ID: {0!s})."
          .format(storage1_copysession_id))

    # Change the delete process according to the copy type.
    r = storage.get("/api/v1/copysession/{0!s}"
                    .format(storage1_copysession_id))
    data = r.json()
    if r.status_code != 200:
        print("Failed to get information of the copy session.")
        print(r)
        print(data)
        return False
    # In the case of REC Consistency, deletion is available after
    # the completion of the copy session suspend.
    if data["type"] == "REC" and data["transfer_mode"] == "Consistency":
        print("Suspending the copy session.")
        if not storage.rec_consistency_suspend(storage1_copysession_id):
            return False
        print("Deleting the copy session.")
        if not storage.copysession_delete(storage1_copysession_id, force=True):
            return False
    # Otherwise
    else:
        print("Deleting the copy session.")
        if not storage.copysession_delete(storage1_copysession_id):
            return False

    print("Succeeded in deleting the copy session.")

    # Logout
    storage.logout()
    return True


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