-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(samples): add suspend/resume samples (#735)
- Loading branch information
1 parent
4cb733f
commit 6ee9020
Showing
3 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright 2022 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 | ||
// | ||
// http://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. | ||
|
||
/** | ||
* Resumes a suspended Google Compute Engine instance (with unencrypted disks). | ||
* | ||
* @param {string} projectId - Project ID or project number of the Cloud project you want to use. | ||
* @param {string} zone - Name of the zone to create the instance in. For example: "us-west3-b" | ||
* @param {string} instanceName - Name of the new virtual machine (VM) instance. | ||
*/ | ||
function main(projectId, zone, instanceName) { | ||
// [START compute_resume_instance] | ||
/** | ||
* TODO(developer): Uncomment and replace these variables before running the sample. | ||
*/ | ||
// const projectId = 'YOUR_PROJECT_ID'; | ||
// const zone = 'europe-central2-b'; | ||
// const instanceName = 'YOUR_INSTANCE_NAME'; | ||
|
||
const compute = require('@google-cloud/compute'); | ||
|
||
// Resumes a suspended Google Compute Engine instance (with unencrypted disks). | ||
async function resumeInstance() { | ||
const instancesClient = new compute.InstancesClient(); | ||
|
||
const [instance] = await instancesClient.get({ | ||
project: projectId, | ||
zone, | ||
instance: instanceName, | ||
}); | ||
|
||
if (instance.status !== 'SUSPENDED') { | ||
throw new Error( | ||
'Only suspended instances can be resumed.' + | ||
`Instance ${instanceName} is in ${instance.status} state.` | ||
); | ||
} | ||
|
||
const [response] = await instancesClient.resume({ | ||
project: projectId, | ||
zone, | ||
instance: instanceName, | ||
}); | ||
let operation = response.latestResponse; | ||
const operationsClient = new compute.ZoneOperationsClient(); | ||
|
||
// Wait for the create operation to complete. | ||
while (operation.status !== 'DONE') { | ||
[operation] = await operationsClient.wait({ | ||
operation: operation.name, | ||
project: projectId, | ||
zone: operation.zone.split('/').pop(), | ||
}); | ||
} | ||
|
||
console.log('Instance resumed.'); | ||
} | ||
|
||
resumeInstance(); | ||
// [END compute_resume_instance] | ||
} | ||
|
||
process.on('unhandledRejection', err => { | ||
console.error(err.message); | ||
process.exitCode = 1; | ||
}); | ||
|
||
main(...process.argv.slice(2)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright 2022 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 | ||
// | ||
// http://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. | ||
|
||
/** | ||
* Suspends a running Google Compute Engine instance. | ||
* | ||
* @param {string} projectId - Project ID or project number of the Cloud project you want to use. | ||
* @param {string} zone - Name of the zone to create the instance in. For example: "us-west3-b" | ||
* @param {string} instanceName - Name of the new virtual machine (VM) instance. | ||
*/ | ||
function main(projectId, zone, instanceName) { | ||
// [START compute_suspend_instance] | ||
/** | ||
* TODO(developer): Uncomment and replace these variables before running the sample. | ||
*/ | ||
// const projectId = 'YOUR_PROJECT_ID'; | ||
// const zone = 'europe-central2-b'; | ||
// const instanceName = 'YOUR_INSTANCE_NAME'; | ||
|
||
const compute = require('@google-cloud/compute'); | ||
|
||
// Suspends a running Google Compute Engine instance. | ||
async function suspendInstance() { | ||
const instancesClient = new compute.InstancesClient(); | ||
|
||
const [response] = await instancesClient.suspend({ | ||
project: projectId, | ||
zone, | ||
instance: instanceName, | ||
}); | ||
let operation = response.latestResponse; | ||
const operationsClient = new compute.ZoneOperationsClient(); | ||
|
||
// Wait for the create operation to complete. | ||
while (operation.status !== 'DONE') { | ||
[operation] = await operationsClient.wait({ | ||
operation: operation.name, | ||
project: projectId, | ||
zone: operation.zone.split('/').pop(), | ||
}); | ||
} | ||
|
||
console.log('Instance suspended.'); | ||
} | ||
|
||
suspendInstance(); | ||
// [END compute_suspend_instance] | ||
} | ||
|
||
process.on('unhandledRejection', err => { | ||
console.error(err.message); | ||
process.exitCode = 1; | ||
}); | ||
|
||
main(...process.argv.slice(2)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// Copyright 2022 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 | ||
// | ||
// http://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 compute = require('@google-cloud/compute'); | ||
|
||
const {describe, it} = require('mocha'); | ||
const cp = require('child_process'); | ||
const {assert} = require('chai'); | ||
|
||
const {generateTestId, getStaleVMInstances, deleteInstance} = require('./util'); | ||
|
||
const instancesClient = new compute.InstancesClient(); | ||
const zoneOperationsClient = new compute.ZoneOperationsClient(); | ||
|
||
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); | ||
|
||
describe('suspend/resume instance tests', () => { | ||
const instanceName = generateTestId(); | ||
const zone = 'europe-central2-b'; | ||
|
||
const delay = ms => new Promise(res => setTimeout(res, ms)); | ||
|
||
const getInstance = async (projectId, zone, instanceName) => { | ||
const [instance] = await instancesClient.get({ | ||
project: projectId, | ||
zone, | ||
instance: instanceName, | ||
}); | ||
return instance; | ||
}; | ||
|
||
after(async () => { | ||
const instances = await getStaleVMInstances(); | ||
await Promise.all( | ||
instances.map(instance => | ||
deleteInstance(instance.zone, instance.instanceName) | ||
) | ||
); | ||
}); | ||
|
||
it('should suspend and resume instance', async () => { | ||
const projectId = await instancesClient.getProjectId(); | ||
|
||
const [insertResponse] = await instancesClient.insert({ | ||
instanceResource: { | ||
name: instanceName, | ||
disks: [ | ||
{ | ||
initializeParams: { | ||
diskSizeGb: '64', | ||
sourceImage: | ||
'projects/ubuntu-os-cloud/global/images/family/ubuntu-2004-lts', | ||
}, | ||
autoDelete: true, | ||
boot: true, | ||
}, | ||
], | ||
machineType: `zones/${zone}/machineTypes/n1-standard-1`, | ||
networkInterfaces: [ | ||
{ | ||
name: 'global/networks/default', | ||
}, | ||
], | ||
}, | ||
project: projectId, | ||
zone, | ||
}); | ||
let operation = insertResponse.latestResponse; | ||
|
||
while (operation.status !== 'DONE') { | ||
[operation] = await zoneOperationsClient.wait({ | ||
operation: operation.name, | ||
project: projectId, | ||
zone: operation.zone.split('/').pop(), | ||
}); | ||
} | ||
|
||
// Once the machine is running, give it some time to fully start all processes | ||
// before trying to suspend it. | ||
await delay(45 * 1000); | ||
|
||
let output = execSync( | ||
`node instances/suspend-resume/suspend ${projectId} ${zone} ${instanceName}` | ||
); | ||
assert.match(output, /Instance suspended./); | ||
|
||
let instance = await getInstance(projectId, zone, instanceName); | ||
|
||
while (instance.status === 'SUSPENDING') { | ||
[instance] = await instancesClient.get({ | ||
project: projectId, | ||
zone, | ||
instance: instanceName, | ||
}); | ||
|
||
await delay(5 * 1000); | ||
} | ||
|
||
instance = await getInstance(projectId, zone, instanceName); | ||
|
||
assert.equal(instance.status, 'SUSPENDED'); | ||
|
||
output = execSync( | ||
`node instances/suspend-resume/resume ${projectId} ${zone} ${instanceName}` | ||
); | ||
assert.match(output, /Instance resumed./); | ||
|
||
instance = await getInstance(projectId, zone, instanceName); | ||
|
||
assert.equal(instance.status, 'RUNNING'); | ||
|
||
execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`); | ||
}); | ||
}); |