diff --git a/compute/disks/createCustomSecondaryDisk.js b/compute/disks/createCustomSecondaryDisk.js new file mode 100644 index 0000000000..db24e59d8b --- /dev/null +++ b/compute/disks/createCustomSecondaryDisk.js @@ -0,0 +1,125 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary_custom] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // If you want to create regional disk, you should use: RegionDisksClient and RegionOperationsClient. + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone or region for the secondary disk. The primary and secondary disks must be in different regions. + // If you use RegionDisksClient- define region, if DisksClient- define zone. + // secondaryLocation = 'us-central1-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone or region for the primary disk. + // If you use RegionDisksClient- define region, if DisksClient- define zone. + // primaryLocation = 'us-central1-b'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + // If you use RegionDisksClient, pass region as an argument instead of zone + zone: secondaryLocation, + type: diskType, + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`, + }), + // Specify additional guest OS features. + // To learn more about OS features, open: `https://cloud.google.com/compute/docs/disks/async-pd/configure?authuser=0#secondary2`. + // You don't need to include the guest OS features of the primary disk. + // The secondary disk automatically inherits the guest OS features of the primary disk. + guestOsFeatures: [ + new compute.GuestOsFeature({ + type: 'NEW_FEATURE_ID_1', + }), + ], + // Assign additional labels to the secondary disk. + // You don't need to include the labels of the primary disk. + // The secondary disk automatically inherits the labels from the primary disk + labels: { + key: 'value', + }, + }); + + const [response] = await disksClient.insert({ + project: secondaryProjectId, + // If you use RegionDisksClient, pass region as an argument instead of zone + zone: secondaryLocation, + diskResource: disk, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + // If you use RegionOperationsClient, pass region as an argument instead of zone + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Custom secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeSecondaryDisk(); + // [END compute_disk_create_secondary_custom] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/createRegionalSecondaryDisk.js b/compute/disks/createRegionalSecondaryDisk.js new file mode 100644 index 0000000000..aa7d9948bc --- /dev/null +++ b/compute/disks/createRegionalSecondaryDisk.js @@ -0,0 +1,108 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary_regional] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a regionDisksClient + const regionDisksClient = new computeLib.RegionDisksClient(); + // Instantiate a regionOperationsClient + const regionOperationsClient = new computeLib.RegionOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await regionDisksClient.getProjectId(); + + // The region for the secondary disk. + // secondaryLocation = 'us-central1'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await regionDisksClient.getProjectId(); + + // The region for the primary disk. + // primaryLocation = 'us-central2'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `regions/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeRegionalSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + region: secondaryLocation, + type: diskType, + replicaZones: [ + `zones/${secondaryLocation}-a`, + `zones/${secondaryLocation}-b`, + ], + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/regions/${primaryLocation}/disks/${primaryDiskName}`, + }), + }); + + const [response] = await regionDisksClient.insert({ + project: secondaryProjectId, + diskResource: disk, + region: secondaryLocation, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + region: secondaryLocation, + }); + } + + console.log(`Secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeRegionalSecondaryDisk(); + // [END compute_disk_create_secondary_regional] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/createZonalSecondaryDisk.js b/compute/disks/createZonalSecondaryDisk.js new file mode 100644 index 0000000000..08ab048433 --- /dev/null +++ b/compute/disks/createZonalSecondaryDisk.js @@ -0,0 +1,104 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone for the secondary disk. The primary and secondary disks must be in different regions. + // secondaryLocation = 'us-central1-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone for the primary disk. + // primaryLocation = 'us-central1-b'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + zone: secondaryLocation, + type: diskType, + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`, + }), + }); + + const [response] = await disksClient.insert({ + project: secondaryProjectId, + zone: secondaryLocation, + diskResource: disk, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeSecondaryDisk(); + // [END compute_disk_create_secondary] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/startReplication.js b/compute/disks/startReplication.js new file mode 100644 index 0000000000..606fb33824 --- /dev/null +++ b/compute/disks/startReplication.js @@ -0,0 +1,91 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_start_replication] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project of the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone of the secondary disk. + // secondaryLocation = 'us-central1-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project of the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone of the primary disk. + // primaryLocation = 'us-central1-a'; + + // The name of the primary disk. + // primaryDiskName = 'primary-disk-name'; + + // Start replication + async function callStartReplication() { + const [response] = await disksClient.startAsyncReplication({ + project: secondaryProjectId, + zone: primaryLocation, + disk: primaryDiskName, + disksStartAsyncReplicationRequestResource: + new compute.DisksStartAsyncReplicationRequest({ + asyncSecondaryDisk: `projects/${primaryProjectId}/zones/${secondaryLocation}/disks/${secondaryDiskName}`, + }), + }); + + let operation = response.latestResponse; + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log( + `Data replication from primary disk: ${primaryDiskName} to secondary disk: ${secondaryDiskName} started.` + ); + } + + await callStartReplication(); + // [END compute_disk_start_replication] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/stopReplication.js b/compute/disks/stopReplication.js new file mode 100644 index 0000000000..845b1463b2 --- /dev/null +++ b/compute/disks/stopReplication.js @@ -0,0 +1,70 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main(primaryDiskName, primaryLocation) { + // [START compute_disk_stop_replication] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone of the primary disk. + // primaryLocation = 'us-central1-a'; + + // The name of the primary disk. + // primaryDiskName = 'primary-disk-name'; + + // Stop replication + async function callStopReplication() { + const [response] = await disksClient.stopAsyncReplication({ + project: primaryProjectId, + zone: primaryLocation, + disk: primaryDiskName, + }); + + let operation = response.latestResponse; + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: primaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Replication for primary disk: ${primaryDiskName} stopped.`); + } + + await callStopReplication(); + // [END compute_disk_stop_replication] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/test/createCustomSecondaryDisk.test.js b/compute/test/createCustomSecondaryDisk.test.js new file mode 100644 index 0000000000..d0429192fc --- /dev/null +++ b/compute/test/createCustomSecondaryDisk.test.js @@ -0,0 +1,103 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); +const {getStaleDisks, deleteDisk} = require('./util'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +const disksClient = new computeLib.DisksClient(); +const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + +async function createDisk(diskName, zone, projectId) { + const [response] = await disksClient.insert({ + project: projectId, + zone, + diskResource: { + sizeGb: 10, + name: diskName, + zone, + type: `zones/${zone}/diskTypes/pd-balanced`, + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +describe('Create compute custom secondary disk', async () => { + const prefix = 'custom-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const secondaryZone = `${secondaryRegion}-a`; + const primaryZone = `${primaryRegion}-a`; + let projectId; + + before(async () => { + projectId = await disksClient.getProjectId(); + await createDisk(primaryDiskName, primaryZone, projectId); + }); + + after(async () => { + // Cleanup resources + const disks = await getStaleDisks(prefix); + await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName))); + }); + + it('should create a custom secondary disk', async () => { + const expectedProperties = { + guestOsFeatures: [{type: 'FEATURE_TYPE_UNSPECIFIED', _type: 'type'}], + labels: { + key: 'value', + }, + }; + execSync( + `node ./disks/createCustomSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + const [disk] = await disksClient.get({ + project: projectId, + zone: secondaryZone, + disk: secondaryDiskName, + }); + + assert.deepEqual(disk.guestOsFeatures, expectedProperties.guestOsFeatures); + assert.deepEqual(disk.labels, expectedProperties.labels); + }); +}); diff --git a/compute/test/createRegionalSecondaryDisk.test.js b/compute/test/createRegionalSecondaryDisk.test.js new file mode 100644 index 0000000000..2a3dde96bd --- /dev/null +++ b/compute/test/createRegionalSecondaryDisk.test.js @@ -0,0 +1,119 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +const disksClient = new computeLib.RegionDisksClient(); +const regionOperationsClient = new computeLib.RegionOperationsClient(); + +async function createDisk(diskName, region) { + const projectId = await disksClient.getProjectId(); + const [response] = await disksClient.insert({ + project: projectId, + region, + diskResource: { + sizeGb: 10, + name: diskName, + region, + type: `regions/${region}/diskTypes/pd-balanced`, + replicaZones: [`zones/${region}-a`, `zones/${region}-b`], + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: projectId, + region, + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +async function deleteDisk(region, diskName) { + const projectId = await disksClient.getProjectId(); + const [response] = await disksClient.delete({ + project: projectId, + disk: diskName, + region, + }); + let operation = response.latestResponse; + + console.log(`Deleting ${diskName}`); + + // Wait for the delete operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: projectId, + region, + }); + } +} + +describe('Create compute regional secondary disk', async () => { + const prefix = 'regional-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const disks = [ + { + diskName: secondaryDiskName, + region: secondaryRegion, + }, + { + diskName: primaryDiskName, + region: primaryRegion, + }, + ]; + + before(async () => { + await createDisk(primaryDiskName, primaryRegion); + }); + + after(async () => { + // Cleanup resources + await Promise.all( + disks.map(disk => deleteDisk(disk.region, disk.diskName)) + ); + }); + + it('should create a regional secondary disk', () => { + const response = execSync( + `node ./disks/createRegionalSecondaryDisk.js ${secondaryDiskName} ${secondaryRegion} ${primaryDiskName} ${primaryRegion}`, + { + cwd, + } + ); + + assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); + }); +}); diff --git a/compute/test/zonalSecondaryDisk.test.js b/compute/test/zonalSecondaryDisk.test.js new file mode 100644 index 0000000000..09765ab4dd --- /dev/null +++ b/compute/test/zonalSecondaryDisk.test.js @@ -0,0 +1,119 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); +const {getStaleDisks, deleteDisk} = require('./util'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +async function createDisk(diskName, zone) { + const disksClient = new computeLib.DisksClient(); + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + const projectId = await disksClient.getProjectId(); + + const [response] = await disksClient.insert({ + project: projectId, + zone, + diskResource: { + sizeGb: 10, + name: diskName, + zone, + type: `zones/${zone}/diskTypes/pd-balanced`, + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +describe('Compute zonal secondary disk', async () => { + const prefix = 'zonal-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const secondaryZone = `${secondaryRegion}-a`; + const primaryZone = `${primaryRegion}-a`; + + before(async () => { + await createDisk(primaryDiskName, primaryZone); + }); + + after(async () => { + // Cleanup resources + const disks = await getStaleDisks(prefix); + await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName))); + }); + + it('should create a zonal secondary disk', () => { + const response = execSync( + `node ./disks/createZonalSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); + }); + + it('should start replication', () => { + const response = execSync( + `node ./disks/startReplication.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert( + response.includes( + `Data replication from primary disk: ${primaryDiskName} to secondary disk: ${secondaryDiskName} started.` + ) + ); + }); + + it('should stop replication', () => { + const response = execSync( + `node ./disks/stopReplication.js ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert( + response.includes( + `Replication for primary disk: ${primaryDiskName} stopped.` + ) + ); + }); +});