Skip to content

Commit 9607aae

Browse files
FrodoTheTrueAce Nassri
authored andcommitted
chore(samples): create windows images samples (#703)
1 parent b4787c5 commit 9607aae

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* Creates a new Windows image from the specified source disk.
17+
*
18+
* @param {string} projectId - Project ID or project number of the Cloud project you use.
19+
* @param {string} zone - Zone of the disk you copy from.
20+
* @param {string} sourceDiskName - Name of the source disk you copy from.
21+
* @param {string} imageName - Name of the image you want to create.
22+
* @param {string} storageLocation - Storage location for the image. If the value is undefined, function will store the image in the multi-region closest to your image's source location.
23+
* @param {boolean} forceCreate - Create the image even if the source disk is attached to a running instance.
24+
*/
25+
function main(
26+
projectId,
27+
zone,
28+
sourceDiskName,
29+
imageName,
30+
storageLocation,
31+
forceCreate = false
32+
) {
33+
// [START compute_windows_image_create]
34+
/**
35+
* TODO(developer): Uncomment and replace these variables before running the sample.
36+
*/
37+
// const projectId = 'YOUR_PROJECT_ID';
38+
// const zone = 'europe-central2-b';
39+
// const sourceDiskName = 'YOUR_SOURCE_DISK_NAME';
40+
// const imageName = 'YOUR_IMAGE_NAME';
41+
// const storageLocation = 'eu';
42+
// const forceCreate = false;
43+
44+
const compute = require('@google-cloud/compute');
45+
46+
function parseInstanceName(name) {
47+
const parsedName = name.split('/');
48+
const l = parsedName.length;
49+
50+
if (parsedName.legth < 5) {
51+
throw new Error(
52+
'Provide correct instance name in the following format: https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME'
53+
);
54+
}
55+
56+
return [parsedName[l - 1], parsedName[l - 3], parsedName[l - 5]];
57+
}
58+
59+
async function createWindowsOSImage() {
60+
const imagesClient = new compute.ImagesClient();
61+
const instancesClient = new compute.InstancesClient();
62+
const disksClient = new compute.DisksClient();
63+
64+
// Getting instances where source disk is attached
65+
const [sourceDisk] = await disksClient.get({
66+
project: projectId,
67+
zone,
68+
disk: sourceDiskName,
69+
});
70+
71+
// Сhecking whether the instances is stopped
72+
for (const fullInstanceName of sourceDisk.users) {
73+
const [instanceName, instanceZone, instanceProjectId] =
74+
parseInstanceName(fullInstanceName);
75+
const [instance] = await instancesClient.get({
76+
project: instanceProjectId,
77+
zone: instanceZone,
78+
instance: instanceName,
79+
});
80+
81+
if (
82+
!['TERMINATED', 'STOPPED'].includes(instance.status) &&
83+
!forceCreate
84+
) {
85+
throw new Error(
86+
`Instance ${instanceName} should be stopped. Please stop the instance using GCESysprep command or set forceCreate parameter to true (not recommended). More information here: https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api.`
87+
);
88+
}
89+
}
90+
91+
if (forceCreate) {
92+
console.warn(
93+
'Warning: forceCreate option compromise the integrity of your image. Stop the instance before you create the image if possible.'
94+
);
95+
}
96+
97+
const [response] = await imagesClient.insert({
98+
project: projectId,
99+
forceCreate,
100+
imageResource: {
101+
name: imageName,
102+
sourceDisk: `/zones/${zone}/disks/${sourceDiskName}`,
103+
storageLocations: storageLocation ? [storageLocation] : [],
104+
},
105+
});
106+
let operation = response.latestResponse;
107+
const operationsClient = new compute.GlobalOperationsClient();
108+
109+
// Wait for the create operation to complete.
110+
while (operation.status !== 'DONE') {
111+
[operation] = await operationsClient.wait({
112+
operation: operation.name,
113+
project: projectId,
114+
});
115+
}
116+
117+
console.log('Image created.');
118+
}
119+
120+
createWindowsOSImage();
121+
// [END compute_windows_image_create]
122+
}
123+
124+
process.on('unhandledRejection', err => {
125+
console.error(err.message);
126+
process.exitCode = 1;
127+
});
128+
129+
const args = process.argv.slice(2);
130+
if (args.length >= 6) {
131+
args[7] = args[7] === 'true';
132+
}
133+
134+
main(...args);
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const compute = require('@google-cloud/compute');
18+
19+
const {describe, it} = require('mocha');
20+
const cp = require('child_process');
21+
const {assert} = require('chai');
22+
23+
const {generateTestId, getStaleVMInstances, deleteInstance} = require('./util');
24+
25+
const instancesClient = new compute.InstancesClient();
26+
const imagesClient = new compute.ImagesClient();
27+
const globalOperationsClient = new compute.GlobalOperationsClient();
28+
const zoneOperationsClient = new compute.ZoneOperationsClient();
29+
30+
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
31+
32+
describe('create windows os image tests', () => {
33+
const instanceName = generateTestId();
34+
const diskName = generateTestId();
35+
const imageName = generateTestId();
36+
const zone = 'europe-central2-b';
37+
38+
after(async () => {
39+
const instances = await getStaleVMInstances();
40+
await Promise.all(
41+
instances.map(instance =>
42+
deleteInstance(instance.zone, instance.instanceName)
43+
)
44+
);
45+
});
46+
47+
it('should create windows os image', async () => {
48+
const projectId = await instancesClient.getProjectId();
49+
50+
const [insertResponse] = await instancesClient.insert({
51+
instanceResource: {
52+
name: instanceName,
53+
disks: [
54+
{
55+
initializeParams: {
56+
diskName: diskName,
57+
diskSizeGb: '64',
58+
sourceImage:
59+
'projects/windows-cloud/global/images/windows-server-2012-r2-dc-core-v20220314',
60+
},
61+
deviceName: diskName,
62+
autoDelete: true,
63+
boot: true,
64+
type: 'PERSISTENT',
65+
},
66+
],
67+
machineType: `zones/${zone}/machineTypes/n1-standard-1`,
68+
networkInterfaces: [
69+
{
70+
name: 'global/networks/default',
71+
},
72+
],
73+
},
74+
project: projectId,
75+
zone,
76+
});
77+
let operation = insertResponse.latestResponse;
78+
79+
while (operation.status !== 'DONE') {
80+
[operation] = await zoneOperationsClient.wait({
81+
operation: operation.name,
82+
project: projectId,
83+
zone: operation.zone.split('/').pop(),
84+
});
85+
}
86+
87+
try {
88+
execSync(
89+
`node instances/windows/creatingWindowsOSImage ${projectId} ${zone} ${diskName} ${imageName}`
90+
);
91+
} catch (err) {
92+
assert.include(
93+
err.stderr.toString(),
94+
`Instance ${instanceName} should be stopped.`
95+
);
96+
}
97+
98+
const outputCreate2 = execSync(
99+
`node instances/windows/creatingWindowsOSImage ${projectId} ${zone} ${diskName} ${imageName} eu true`
100+
);
101+
assert.match(outputCreate2, /Image created./);
102+
103+
const [deleteResponse] = await imagesClient.delete({
104+
project: projectId,
105+
image: imageName,
106+
});
107+
operation = deleteResponse.latestResponse;
108+
109+
while (operation.status !== 'DONE') {
110+
[operation] = await globalOperationsClient.wait({
111+
operation: operation.name,
112+
project: projectId,
113+
});
114+
}
115+
116+
execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`);
117+
});
118+
});

0 commit comments

Comments
 (0)