Automating clone of OCI compute instances across regions

This post is also available in: Português

Oracle is constantly releasing new regions around the globe for the Oracle Cloud Infrastructure, and geolocation is something very important for companies specially to achieve low latencies and high throughput.

After those regions are out, I've been asked for some customers to move their existing computes from one region to another. After doing the same steps for about 3 times, I decided to automate it in a script and share with the community =]

The script is public available at my github oci-scripts page: oci_compute_clone_xregion.sh

Before we start

So, when thinking about moving something from one region to another, usually there are 2 very important things to consider:

1. Migrate it consistently among all attached volumes (and boot-volume).

Reason item 1 is important is because if you copy the boot-volumes and volumes on different point-of-times, you will probably end-up in an inconsistent state of your server. Imagine, ie, an Oracle Database where the datafiles and logfiles are spread over multiple volumes.

2. Do it fully online, without stopping the original compute (specially when cloning for dev provisioning).

And item 2 is to ensure we won't impact the original environment while performing the cloning operation. This script can also be used to provision dev environments without stopping prod. If you intend to move  a production application from one region to another, in this case you may need to STOP de source so nothing gets written after the cloning operation starts.

How does it work?

The oci_compute_clone_xregion.sh is a 100% public bash shell script tool that will execute several steps.

The script was written after I had to perform the same set of instructions manually a lot of times. It is not complex. It works by getting all the current information of machine in JSON, including the attached disks, attached vnics, etc. Then it will take the compute backup, move it to the other region and create a clone machine using the same properties.

I've end up with the following steps

1 - Create Volume Group with source instance Boot-Volume and Volumes.
2 - Backup Volume Group.
  ↳ Will  create a volume group with all your compute instance attached volumes and take a backup of it, to ensure they will all be in the same point of time.
3 - Remove Volume Group.
↳ Now we don't need the volume group created on step 1 anymore. We can remove it (note the backup of item 2 will be kept).
4 - Create a New Boot-Volume from the Backup.
5 - Create a Temporary cloned Compute Instance from the Boot Volume.
↳ We can't transfer boot-volumes across regions, only compute images. However, to create an image of a compute, the instance is stopped. To avoid stopping our source compute (which may be in use for production), we create a temporary compute from the original boot-volume backup (item 2) just to create an image of it without affecting the source.
6 - Stop the Temporary cloned Compute Instance.
7 - Create an Image from it.
↳ Now we take the image of the temporary cloned compute to transfer across the regions.
8 - Remove the Temporary cloned Compute Instance and Boot-Volume.
↳ We don't need it anymore.

9 - Move the image from source to target.
↳ Now we need to move the image to the target region. This image will be used to generate the final cloned compute.

10 - Remove Image on source region.
11- Create a Compute Instance from Image on target region.
↳ The new compute is now created on the target region.

12 - Remove Image on target region.
13 - Move Volumes Backups from Source Region to Target Region.
↳ Now it's time to move the volumes backups created on step 2. The target instance must have the same attached volumes as the source.

14 - Remove Volumes Backups in Source Region.
↳ We can remove the backups created on step 2 as we already have everything we need on the target region.

15 - Create Volumes from backups in Target Region.
16 - Remove Volumes Backups in Target Region.
17 - Attach Volumes in target.
↳ We create volumes from the backups, remove the backups and then attach the new volumes to the new instance, so we have it just like the original.
18 - Run iscsiadm commands on target (if Linux).
↳ Finally, the iscsiadm commands are created and printed out on the screen to map all the new volumes.

Note that the steps 13-18 will be skipped if the source instance has no attached volumes.

Script Usage:

Script latest version can be downloaded from github at: https://github.com/dbarj/oci-scripts/blob/master/oci_compute_clone_xregion.sh

$ oci_compute_clone_xregion.sh -h
Usage: oci_compute_clone_xregion.sh -i <value> [-n <value>] [-p <value>] [-s <value>] [-a <value>] [-t <value>] [-r <value>] [-b <value>] [-c <value>] [-q] [-x]

Only "-i" is mandatory. All other parameters if omitted will be asked during execution.

-i  : Source Compute Instance Name or OCID
-n  : Target Compute Instance Name
-p  : Target Compute Shape
-s  : Target Subnet ID
-a  : Target IP Address
-t  : Target Region
-r  : Source Region
-b  : Object Storage Bucket Name
-c  : Clone Subnet ID
-h  : Show this output.
-q  : Quiet mode. Will suppress the spool of executed OCI-CLI commands.
-x  : Will try to run step 22 automatically on new target. Default is off. Note you need a password-less SSH connection to the target with opc.

Basically the only mandatory parameter is the source Compute Instance display name or OCID, specified with [-i]. All the others will be interactively asked if not specified.

Some details:

[-b] = To move a compute image across regions, it must be stored on a local Object Storage. I recommend to use a Standard Private OS for this.

[-c] = As mentioned before, to create the source compute image without affecting the availability on source, a local temporary replica is created. This parameter specifies where the local replica is gonna be placed. For some specific scenarios, you may want to keep it in a isolated compartment/vpn/subnet.

[-q] = During each step you can see the currently being executed oci-cli command. Use this option to suppress it.

[-x] = Check "Execution Example" step 22 for more details.

Note that before running anything, the script does multiple validations to ensure the given values are valid.

Pre-requisites

The oci_compute_clone_xregion.sh depends that you have a bash shell, jq and oci_image_clone_xregion.sh.

Bash Shell

Bash is the GNU Project's shell. It’s available on most UNIX operating systems, like Linux and Mac.

JQ

JQ stands for Json Query, it’s a parser that is required to generate and process JSON files generated by cURL. It’s available at https://github.com/stedolan/jq/releases

[user@localhost ~]$ cd ~/bin
[user@localhost ~]$ wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64
100%[===========================================>] 2.89M 862KB/s in 3.8s
2018-09-17 18:55:00 (776 KB/s) - ‘jq’ saved [3027945/3027945]
[user@localhost ~]$ chmod +x jq
[user@localhost ~]$ export PATH=$PATH:`pwd`
[user@localhost ~]$ which jq
/Users/myuser/bin/jq

Some linux distributions also provides JQ straight from the yum repository.

oci_image_clone_xregion.sh

The oci_image_clone_xregion.sh is another script in my github repo that will handle the step 9 of the flow. The script must simply be placed in the same directory.

Execution Example:

Note: OCID values were masked for security.

Calling the script. Note I've passed all parameters, however only the [-i] is mandatory.

$ oci_compute_clone_xregion.sh \
-i ocid1.instance.oc1.iad.sss \
-n OCSPNPRDORADB01 \
-p VM.Standard2.8 \
-s ocid1.subnet.oc1.sa-saopaulo-1.ccc \
-a 172.16.X.X \
-r us-ashburn-1 \
-t sa-saopaulo-1 \
-b REGION_MIGRATION
Checking Compute Name and OCID.
Compute Name: OCASNPRDORADB01
Compute OCID: ocid1.instance.oc1.iad.sss
Getting OCI Compute information..
The Source machine will be temporarily cloned within the same region, so an image can be created without stopping it.
Options:
- YES
- NO
Create temporary Clone Compute machine in same subnet as the source [YES]:

This question was made because I haven't passed the [-c] parameter, specifying where I want to create the temporary cloned instance. If you answer YES, it will be created at the same subnet as the source. If you answer NO, you will be asked for the compartment, vcn and subnet names.

Before the script get started, it will print once again all the overall steps.

Starting execution.
Steps:
01 - Create Volume Group with instance Boot-Volume and Volumes.
02 - Backup Volume Group.
03 - Remove Volume Group.
04 - Create a New Boot-Volume from the Backup.
05 - Create a Temporary cloned Compute Instance from the Boot Volume.
06 - Stop the Temporary cloned Compute Instance.
07 - Create an Image from it.
08 - Remove the Temporary cloned Compute Instance and Boot-Volume.
09-13 - Move the image from source to target (oci_image_clone_xregion.sh).
14 - Remove Image on source region.
15 - Create a Compute Instance from Image on target region.
16 - Remove Image on target region.
17 - Move Volumes Backups from Source Region to Target Region.
18 - Remove Volumes Backups in Source Region.
19 - Create Volumes from backups in Target Region.
20 - Remove Volumes Backups in Target Region.
21 - Attach Volumes in target.
22 - Run iscsiadm commands on target (if Linux).

During the execution, you will be able to see each oci-cli command executed by the steps of the shell.

Executing Step 1

++ oci --cli-rc-file /dev/null --region us-ashburn-1 bv volume-group create --compartment-id ocid1.compartment.oc1..fff --availability-domain XkLK:US-ASHBURN-AD-1 --display-name OCASNPRDORADB01_VG --max-wait-seconds 3600 --wait-for-state AVAILABLE --source-details '{"type":"volumeIds","volumeIds": ["ocid1.bootvolume.oc1.iad.mmm","ocid1.volume.oc1.iad.ppp"]}'
Action completed. Waiting until the resource has entered state: ('AVAILABLE',)
+ v_orig_VGJson='{
  "data": {
    "availability-domain": "XkLK:US-ASHBURN-AD-1",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_VG",
    "freeform-tags": {},
    "id": "ocid1.volumegroup.oc1.iad.kkk",
    "is-hydrated": null,
    "lifecycle-state": "AVAILABLE",
    "size-in-gbs": 410,
    "size-in-mbs": 419840,
    "source-details": {
      "type": "volumeIds",
      "volume-ids": [
        "ocid1.bootvolume.oc1.iad.mmm",
        "ocid1.volume.oc1.iad.ppp"
      ]
    },
    "time-created": "2019-10-27T20:30:37.909000+00:00",
    "volume-ids": [
      "ocid1.bootvolume.oc1.iad.mmm",
      "ocid1.volume.oc1.iad.ppp"
    ]
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 2

++ oci --cli-rc-file /dev/null --region us-ashburn-1 bv volume-group-backup create --compartment-id ocid1.compartment.oc1..fff --volume-group-id ocid1.volumegroup.oc1.iad.kkk --display-name OCASNPRDORADB01_VG_BKP --type INCREMENTAL --wait-for-state AVAILABLE --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('AVAILABLE',)
+ v_orig_VGBackupJson='{
  "data": {
    "compartment-id": "ocid1.compartment.oc1..fff",
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_VG_BKP",
    "freeform-tags": {},
    "id": "ocid1.volumegroupbackup.oc1.iad.jjj",
    "lifecycle-state": "AVAILABLE",
    "size-in-gbs": 410,
    "size-in-mbs": 419840,
    "time-created": "2019-10-27T20:30:57.562000+00:00",
    "time-request-received": "2019-10-27T20:30:41.218000+00:00",
    "type": "INCREMENTAL",
    "unique-size-in-gbs": 145,
    "unique-size-in-mbs": 147762,
    "volume-backup-ids": [
      "ocid1.bootvolumebackup.oc1.iad.qqq",
      "ocid1.volumebackup.oc1.iad.nnn"
    ],
    "volume-group-id": "ocid1.volumegroup.oc1.iad.kkk"
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 3

+ oci --cli-rc-file /dev/null --region us-ashburn-1 bv volume-group delete --volume-group-id ocid1.volumegroup.oc1.iad.kkk --force --wait-for-state TERMINATED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('TERMINATED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 4

++ oci --cli-rc-file /dev/null --region us-ashburn-1 bv boot-volume create --boot-volume-backup-id ocid1.bootvolumebackup.oc1.iad.qqq --display-name OCASNPRDORADB01_CLONE_BV --availability-domain XkLK:US-ASHBURN-AD-1 --wait-for-state AVAILABLE --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('AVAILABLE',)
+ v_clone_BVJson='{
  "data": {
    "availability-domain": "XkLK:US-ASHBURN-AD-1",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_CLONE_BV",
    "freeform-tags": {},
    "id": "ocid1.bootvolume.oc1.iad.ooo",
    "image-id": "ocid1.image.oc1.iad.aaa",
    "is-hydrated": false,
    "kms-key-id": null,
    "lifecycle-state": "AVAILABLE",
    "size-in-gbs": 100,
    "size-in-mbs": 102400,
    "source-details": {
      "id": "ocid1.bootvolumebackup.oc1.iad.qqq",
      "type": "bootVolumeBackup"
    },
    "system-tags": {},
    "time-created": "2019-10-27T20:33:22.981000+00:00",
    "volume-group-id": null
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 5

++ oci --cli-rc-file /dev/null --region us-ashburn-1 compute instance launch --compartment-id ocid1.compartment.oc1..fff --availability-domain XkLK:US-ASHBURN-AD-1 --shape VM.Standard2.1 --wait-for-state RUNNING --max-wait-seconds 3600 --display-name OCASNPRDORADB01_CLONE_INST --source-boot-volume-id ocid1.bootvolume.oc1.iad.ooo --subnet-id ocid1.subnet.oc1.iad.ddd --assign-public-ip false
Action completed. Waiting until the resource has entered state: ('RUNNING',)
+ v_clone_instJson='{
  "data": {
    "agent-config": {
      "is-monitoring-disabled": false
    },
    "availability-domain": "XkLK:US-ASHBURN-AD-1",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "dedicated-vm-host-id": null,
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_CLONE_INST",
    "extended-metadata": {},
    "fault-domain": "FAULT-DOMAIN-1",
    "freeform-tags": {},
    "id": "ocid1.instance.oc1.iad.ttt",
    "image-id": "ocid1.image.oc1.iad.aaa",
    "ipxe-script": null,
    "launch-mode": "NATIVE",
    "launch-options": {
      "boot-volume-type": "PARAVIRTUALIZED",
      "firmware": "UEFI_64",
      "is-consistent-volume-naming-enabled": true,
      "is-pv-encryption-in-transit-enabled": true,
      "network-type": "PARAVIRTUALIZED",
      "remote-data-volume-type": "PARAVIRTUALIZED"
    },
    "lifecycle-state": "RUNNING",
    "metadata": {},
    "region": "iad",
    "shape": "VM.Standard2.1",
    "source-details": {
      "boot-volume-id": "ocid1.bootvolume.oc1.iad.ooo",
      "source-type": "bootVolume"
    },
    "system-tags": {},
    "time-created": "2019-10-27T20:33:41.886000+00:00",
    "time-maintenance-reboot-due": null
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 6

+ oci --cli-rc-file /dev/null --region us-ashburn-1 compute instance action --instance-id ocid1.instance.oc1.iad.ttt --action STOP --wait-for-state STOPPED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('STOPPED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 7

++ oci --cli-rc-file /dev/null --region us-ashburn-1 compute image create --compartment-id ocid1.compartment.oc1..fff --display-name OCASNPRDORADB01_IMAGE --instance-id ocid1.instance.oc1.iad.ttt --wait-for-state AVAILABLE --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('AVAILABLE',)
+ v_clone_imageJson='{
  "data": {
    "agent-features": null,
    "base-image-id": "ocid1.image.oc1.iad.aaa",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "create-image-allowed": true,
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_IMAGE",
    "freeform-tags": {},
    "id": "ocid1.image.oc1.iad.eee",
    "launch-mode": "NATIVE",
    "launch-options": {
      "boot-volume-type": "PARAVIRTUALIZED",
      "firmware": "UEFI_64",
      "is-consistent-volume-naming-enabled": true,
      "is-pv-encryption-in-transit-enabled": true,
      "network-type": "PARAVIRTUALIZED",
      "remote-data-volume-type": "PARAVIRTUALIZED"
    },
    "lifecycle-state": "AVAILABLE",
    "operating-system": "Oracle Linux",
    "operating-system-version": "6.10",
    "size-in-mbs": 102400,
    "time-created": "2019-10-27T20:34:57.238000+00:00"
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 8

+ oci --cli-rc-file /dev/null --region us-ashburn-1 compute instance terminate --instance-id ocid1.instance.oc1.iad.ttt --preserve-boot-volume false --force --wait-for-state TERMINATED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('TERMINATED',)
+ v_ret=0
+ ((  1  ))
+ set +x

The steps 9-14 are executed by oci_image_clone_xregion.sh. Before the sub-script get started, it will print all the overall steps.

Steps:
09 - Export the Image.
10 - Create Pre-Auth URL.
11 - Import the Image in target region.
12 - Remove exported Image object.
13 - Remove Pre-Auth URL.

Executing Step 9

++ oci --cli-rc-file /dev/null --region us-ashburn-1 compute image export to-object --image-id ocid1.image.oc1.iad.eee --namespace mytenancy --bucket-name REGION_MIGRATION --name OCASNPRDORADB01_IMAGE_IMAGE_EXPORT
+ v_jsonImageExport='{
  "data": {
    "agent-features": null,
    "base-image-id": "ocid1.image.oc1.iad.aaa",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "create-image-allowed": true,
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_IMAGE",
    "freeform-tags": {},
    "id": "ocid1.image.oc1.iad.eee",
    "launch-mode": "NATIVE",
    "launch-options": {
      "boot-volume-type": "PARAVIRTUALIZED",
      "firmware": "UEFI_64",
      "is-consistent-volume-naming-enabled": true,
      "is-pv-encryption-in-transit-enabled": true,
      "network-type": "PARAVIRTUALIZED",
      "remote-data-volume-type": "PARAVIRTUALIZED"
    },
    "lifecycle-state": "EXPORTING",
    "operating-system": "Oracle Linux",
    "operating-system-version": "6.10",
    "size-in-mbs": 102400,
    "time-created": "2019-10-27T20:34:57.238000+00:00"
  },
  "etag": "xxx",
  "opc-work-request-id": "ocid1.coreservicesworkrequest.oc1.iad.lll"
}'
+ v_ret=0
+ ((  1  ))
+ set +x
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.
Image status is EXPORTING. Please wait.

Executing Step 10

++ oci --cli-rc-file /dev/null --region us-ashburn-1 os preauth-request create --namespace mytenancy --bucket-name REGION_MIGRATION --object-name OCASNPRDORADB01_IMAGE_IMAGE_EXPORT --name OCASNPRDORADB01_IMAGE_PREAUTH --access-type ObjectRead --time-expires 2019-10-29
+ v_jsonPreAuthReq='{
  "data": {
    "access-type": "ObjectRead",
    "access-uri": "/p/xxx/n/mytenancy/b/REGION_MIGRATION/o/OCASNPRDORADB01_IMAGE_IMAGE_EXPORT",
    "id": "xxx=:OCASNPRDORADB01_IMAGE_IMAGE_EXPORT",
    "name": "OCASNPRDORADB01_IMAGE_PREAUTH",
    "object-name": "OCASNPRDORADB01_IMAGE_IMAGE_EXPORT",
    "time-created": "2019-10-27T21:07:24.884000+00:00",
    "time-expires": "2019-10-29T00:00:00+00:00"
  }
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 11

++ oci --cli-rc-file /dev/null --region sa-saopaulo-1 compute image import from-object-uri --compartment-id ocid1.compartment.oc1..fff --display-name OCASNPRDORADB01_IMAGE --launch-mode NATIVE --source-image-type QCOW2 --uri https://objectstorage.us-ashburn-1.oraclecloud.com/p/xxx/n/mytenancy/b/REGION_MIGRATION/o/OCASNPRDORADB01_IMAGE_IMAGE_EXPORT --freeform-tags '{"Source_OCID":"ocid1.image.oc1.iad.eee"}'
+ v_jsonImageImport='{
  "data": {
    "agent-features": null,
    "base-image-id": null,
    "compartment-id": "ocid1.compartment.oc1..fff",
    "create-image-allowed": true,
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_IMAGE",
    "freeform-tags": {
      "Source_OCID": "ocid1.image.oc1.iad.eee"
    },
    "id": "ocid1.image.oc1.sa-saopaulo-1.bbb",
    "launch-mode": "NATIVE",
    "launch-options": {
      "boot-volume-type": "ISCSI",
      "firmware": "UEFI_64",
      "is-consistent-volume-naming-enabled": false,
      "is-pv-encryption-in-transit-enabled": false,
      "network-type": "VFIO",
      "remote-data-volume-type": "PARAVIRTUALIZED"
    },
    "lifecycle-state": "IMPORTING",
    "operating-system": "Custom",
    "operating-system-version": "Custom",
    "size-in-mbs": null,
    "time-created": "2019-10-27T21:07:26.656000+00:00"
  },
  "etag": "xxx",
  "opc-work-request-id": "ocid1.coreservicesworkrequest.oc1.sa-saopaulo-1.ggg"
}'
+ v_ret=0
+ ((  1  ))
+ set +x
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.
Image status is IMPORTING. Please wait.

Executing Step 12

+ oci --cli-rc-file /dev/null --region us-ashburn-1 os object delete --namespace mytenancy --bucket-name REGION_MIGRATION --object-name OCASNPRDORADB01_IMAGE_IMAGE_EXPORT --force
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 13

+ oci --cli-rc-file /dev/null --region us-ashburn-1 os preauth-request delete --namespace mytenancy --bucket-name REGION_MIGRATION --par-id xxx=:OCASNPRDORADB01_IMAGE_IMAGE_EXPORT --force
+ v_ret=0
+ ((  1  ))
+ set +x
++ oci --cli-rc-file /dev/null --region sa-saopaulo-1 compute image list --compartment-id ocid1.compartment.oc1..fff
++ jq -rc '.data[] | select (."freeform-tags"."Source_OCID"=="ocid1.image.oc1.iad.eee")'
+ v_target_imageJson='{"agent-features":null,"base-image-id":null,"compartment-id":"ocid1.compartment.oc1..fff","create-image-allowed":true,"defined-tags":{},"display-name":"OCASNPRDORADB01_IMAGE","freeform-tags":{"Source_OCID":"ocid1.image.oc1.iad.eee"},"id":"ocid1.image.oc1.sa-saopaulo-1.bbb","launch-mode":"NATIVE","launch-options":{"boot-volume-type":"PARAVIRTUALIZED","firmware":"UEFI_64","is-consistent-volume-naming-enabled":true,"is-pv-encryption-in-transit-enabled":true,"network-type":"PARAVIRTUALIZED","remote-data-volume-type":"PARAVIRTUALIZED"},"lifecycle-state":"AVAILABLE","operating-system":"Custom","operating-system-version":"Custom","size-in-mbs":102400,"time-created":"2019-10-27T21:07:26.656000+00:00"}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 14

+ oci --cli-rc-file /dev/null --region us-ashburn-1 compute image delete --image-id ocid1.image.oc1.iad.eee --force --wait-for-state DELETED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('DELETED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 15

++ oci --cli-rc-file /dev/null --region sa-saopaulo-1 compute instance launch --skip-source-dest-check true --assign-public-ip false --metadata '{"ssh_authorized_keys":"ssh-rsa xxx"}' --fault-domain FAULT-DOMAIN-2 --is-pv-encryption-in-transit-enabled true --launch-options '{"bootVolumeType": "PARAVIRTUALIZED","firmware": "UEFI_64","isConsistentVolumeNamingEnabled": "true","networkType": "VFIO","remoteDataVolumeType": "PARAVIRTUALIZED"}' --availability-domain XkLK:SA-SAOPAULO-1-AD-1 --shape VM.Standard2.8 --wait-for-state RUNNING --max-wait-seconds 3600 --display-name OCSPNPRDORADB01 --image-id ocid1.image.oc1.sa-saopaulo-1.bbb --subnet-id ocid1.subnet.oc1.sa-saopaulo-1.ccc --private-ip 172.16.X.X --compartment-id ocid1.compartment.oc1..fff
Action completed. Waiting until the resource has entered state: ('RUNNING',)
+ v_target_instJson='{
  "data": {
    "agent-config": {
      "is-monitoring-disabled": false
    },
    "availability-domain": "XkLK:SA-SAOPAULO-1-AD-1",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "dedicated-vm-host-id": null,
    "defined-tags": {},
    "display-name": "OCSPNPRDORADB01",
    "extended-metadata": {},
    "fault-domain": "FAULT-DOMAIN-2",
    "freeform-tags": {},
    "id": "ocid1.instance.oc1.sa-saopaulo-1.rrr",
    "image-id": "ocid1.image.oc1.sa-saopaulo-1.bbb",
    "ipxe-script": null,
    "launch-mode": "NATIVE",
    "launch-options": {
      "boot-volume-type": "PARAVIRTUALIZED",
      "firmware": "UEFI_64",
      "is-consistent-volume-naming-enabled": true,
      "is-pv-encryption-in-transit-enabled": true,
      "network-type": "VFIO",
      "remote-data-volume-type": "PARAVIRTUALIZED"
    },
    "lifecycle-state": "RUNNING",
    "metadata": {
      "ssh_authorized_keys": "ssh-rsa xxx"
    },
    "region": "sa-saopaulo-1",
    "shape": "VM.Standard2.8",
    "source-details": {
      "boot-volume-size-in-gbs": null,
      "image-id": "ocid1.image.oc1.sa-saopaulo-1.bbb",
      "kms-key-id": null,
      "source-type": "image"
    },
    "system-tags": {},
    "time-created": "2019-10-27T21:43:59.348000+00:00",
    "time-maintenance-reboot-due": null
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 16

+ oci --cli-rc-file /dev/null --region sa-saopaulo-1 compute image delete --image-id ocid1.image.oc1.sa-saopaulo-1.bbb --force --wait-for-state DELETED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('DELETED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 17

There are backups with status CREATING in target. Please wait.
++ oci --cli-rc-file /dev/null --region us-ashburn-1 bv backup copy --volume-backup-id ocid1.volumebackup.oc1.iad.nnn --destination-region sa-saopaulo-1
+ v_target_volBackupJson='{
  "data": {
    "compartment-id": "ocid1.compartment.oc1..fff",
    "defined-tags": {},
    "display-name": "OCASNPRDORADB01_U02_backup_20191027_203041",
    "expiration-time": null,
    "freeform-tags": {},
    "id": "ocid1.volumebackup.oc1.sa-saopaulo-1.iii",
    "kms-key-id": null,
    "lifecycle-state": "CREATING",
    "size-in-gbs": 310,
    "size-in-mbs": 317440,
    "source-type": "MANUAL",
    "source-volume-backup-id": "ocid1.volumebackup.oc1.iad.nnn",
    "system-tags": null,
    "time-created": "2019-10-27T20:30:57.562000+00:00",
    "time-request-received": "2019-10-27T20:30:41.202000+00:00",
    "type": "FULL",
    "unique-size-in-gbs": 0,
    "unique-size-in-mbs": 0,
    "volume-id": "ocid1.volume.oc1.iad.ppp"
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x
Backup status is CREATING. Please wait.
Backup status is CREATING. Please wait.
Backup status is CREATING. Please wait.
Backup status is CREATING. Please wait.

Executing Step 18

+ oci --cli-rc-file /dev/null --region us-ashburn-1 bv volume-group-backup delete --volume-group-backup-id ocid1.volumegroupbackup.oc1.iad.jjj --force --wait-for-state TERMINATED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('TERMINATED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 19

++ oci --cli-rc-file /dev/null --region us-ashburn-1 bv volume-backup-policy-assignment get-volume-backup-policy-asset-assignment --asset-id ocid1.volume.oc1.iad.ppp
++ jq -rc '.data[]."policy-id"'
+ v_origVolBkpPolID=
+ v_ret=0
+ ((  1  ))
+ set +x
++ oci --cli-rc-file /dev/null --region sa-saopaulo-1 bv volume create --compartment-id ocid1.compartment.oc1..fff --display-name OCSPNPRDORADB01_U02 --availability-domain XkLK:SA-SAOPAULO-1-AD-1 --volume-backup-id ocid1.volumebackup.oc1.sa-saopaulo-1.iii --wait-for-state AVAILABLE --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('AVAILABLE',)
+ v_target_volJson='{
  "data": {
    "availability-domain": "XkLK:SA-SAOPAULO-1-AD-1",
    "compartment-id": "ocid1.compartment.oc1..fff",
    "defined-tags": {},
    "display-name": "OCSPNPRDORADB01_U02",
    "freeform-tags": {},
    "id": "ocid1.volume.oc1.sa-saopaulo-1.hhh",
    "is-hydrated": false,
    "kms-key-id": null,
    "lifecycle-state": "AVAILABLE",
    "size-in-gbs": 310,
    "size-in-mbs": 317440,
    "source-details": {
      "id": "ocid1.volumebackup.oc1.sa-saopaulo-1.iii",
      "type": "volumeBackup"
    },
    "system-tags": {},
    "time-created": "2019-10-27T22:00:59.268000+00:00",
    "volume-group-id": null
  },
  "etag": "xxx"
}'
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 20

+ oci --cli-rc-file /dev/null --region sa-saopaulo-1 bv backup delete --volume-backup-id ocid1.volumebackup.oc1.sa-saopaulo-1.iii --force --wait-for-state TERMINATED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('TERMINATED',)
+ v_ret=0
+ ((  1  ))
+ set +x
Could not remove Target Volume Backup.

Executing Step 21

+ oci --cli-rc-file /dev/null --region sa-saopaulo-1 compute volume-attachment attach --instance-id ocid1.instance.oc1.sa-saopaulo-1.rrr --type iscsi --volume-id ocid1.volume.oc1.sa-saopaulo-1.hhh --is-read-only false --wait-for-state ATTACHED --max-wait-seconds 3600
Action completed. Waiting until the resource has entered state: ('ATTACHED',)
+ v_ret=0
+ ((  1  ))
+ set +x

Executing Step 22

## IF YOUR INSTANCE IS LINUX, CONNECT AS OPC AND EXECUTE:
## ================================================================================
sudo iscsiadm -m node -T iqn.2015-12.com.oracleiaas:a9e0e239-a3a5-433b-b353-d4d0b74a7378 -p 169.254.2.2:3260 -u
sudo iscsiadm -m node -o delete -T iqn.2015-12.com.oracleiaas:a9e0e239-a3a5-433b-b353-d4d0b74a7378 -p 169.254.2.2:3260
sudo iscsiadm -m node -o new -T iqn.2015-12.com.oracleiaas:829d03f9-530a-4f74-9315-135d30c6d955 -p 169.254.2.2:3260
sudo iscsiadm -m node -o update -T iqn.2015-12.com.oracleiaas:829d03f9-530a-4f74-9315-135d30c6d955 -n node.startup -v automatic
sudo iscsiadm -m node -T iqn.2015-12.com.oracleiaas:829d03f9-530a-4f74-9315-135d30c6d955 -p 169.254.2.2:3260 -l
## ================================================================================

SCRIPT EXECUTED SUCCESSFULLY

Machine was successfully cloned to the target environment. Now the script will provide the ISCSI commands to detected the new Block Volumes, if the machine had any. Note that if I passed [-x], this step would be executed automatically using the opc account. A password-less connection with the account is needed in order to work.

And that's it. Machine is ready in new region.

Some missing components

Note that some very specific things related to your compute, like a Network Security Groups association, that are not associated with the cloned instance as it relies on the object creation on the target. You will need to assign it manually.

Hope this helps..

Have you enjoyed? Please leave a comment or give a 👍!

2 comments

    • Terry Dupureur on April 9, 2020 at 18:00
    • Reply

    Great scripting Rodrigo!

    Q: As I do some experimenting with this. I happen to be trying this in the OCI Cloud Shell environment. If my cloud shell terminates ore is disconnected for any reason, the shell starts fresh at the bash login prompt. How can I restart this script at a certain step, after I know that certain previous steps have completed successfully?

    Thanks!

    • Nick on November 21, 2024 at 10:54
    • Reply

    Thanks for this post. I am in the process of doing something similar. I did notice the following under step 5.

    We can't transfer boot-volumes across regions, only compute images

    What did you mean by this? i am currently replicating boot volumes that are part of a volume group from one region to another in OCI.

    Are you familiar with Full Stack DR? will Full Stack DR help automate this process at all?

    Thanks

Leave a Reply

Your email address will not be published.