diff --git a/compute/disks/createSecondaryDisk.js b/compute/disks/createSecondaryDisk.js new file mode 100644 index 00000000000..78a6a9aec48 --- /dev/null +++ b/compute/disks/createSecondaryDisk.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 = 'europe-west4-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 = 'europe-central2-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/test/createSecondaryDisk.test.js b/compute/test/createSecondaryDisk.test.js new file mode 100644 index 00000000000..94bc687139c --- /dev/null +++ b/compute/test/createSecondaryDisk.test.js @@ -0,0 +1,87 @@ +/* + * 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('Create compute secondary disk', async () => { + const prefix = 'compute-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryZone = 'europe-west4-a'; + const primaryZone = 'europe-central2-b'; + + 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/createSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); + }); +});