Skip to content

Commit a1ca168

Browse files
authored
chore(samples): add custom machine type samples (#742)
1 parent 91769bf commit a1ca168

File tree

6 files changed

+1025
-0
lines changed

6 files changed

+1025
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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 VM instance with a custom machine type.
17+
*
18+
* @param {string} projectId - ID or number of the project you want to use.
19+
* @param {string} zone - Name of the zone you want to use, for example: us-west3-b
20+
* @param {string} instanceName - Name of the new machine.
21+
* @param {string} cpuSeries - Type of CPU you want to use.
22+
* @param {int} coreCount - Number of CPU cores you want to use.
23+
* @param {int} memory - The amount of memory for the VM instance, in megabytes.
24+
*/
25+
function main(projectId, zone, instanceName, cpuSeries, coreCount, memory) {
26+
// [START compute_custom_machine_type_create_with_helper]
27+
/**
28+
* TODO(developer): Uncomment and replace these variables before running the sample.
29+
*/
30+
// const projectId = 'YOUR_PROJECT_ID';
31+
// const zone = 'europe-central2-b';
32+
// const instanceName = 'YOUR_INSTANCE_NAME';
33+
// const cpuSeries = 'N1';
34+
// const coreCount = 2
35+
// const memory = 256
36+
37+
const compute = require('@google-cloud/compute');
38+
39+
function range(from, to, step) {
40+
return [...Array(Math.floor((to - from) / step) + 1)].map(
41+
(_, i) => from + i * step
42+
);
43+
}
44+
45+
class CustomMachineType {
46+
constructor(zone, cpuSeries, coreCount, memory) {
47+
this.zone = zone;
48+
this.cpuSeries = cpuSeries;
49+
this.coreCount = coreCount;
50+
this.memory = memory;
51+
52+
this.N1 = 'custom';
53+
this.N2 = 'n2-custom';
54+
this.N2D = 'n2d-custom';
55+
this.E2 = 'e2-custom';
56+
this.E2Micro = 'e2-custom-micro';
57+
this.E2Small = 'e2-custom-small';
58+
this.E2Medium = 'e2-custom-medium';
59+
60+
this.CpuSeriesE2Limit = {
61+
allowedCores: range(2, 33, 2),
62+
minMemPerCore: 512,
63+
maxMemPerCore: 8192,
64+
allowExtraMemory: false,
65+
extraMemoryLimit: 0,
66+
};
67+
68+
this.CpuSeriesE2MicroLimit = {
69+
allowedCores: [],
70+
minMemPerCore: 1024,
71+
maxMemPerCore: 2048,
72+
allowExtraMemory: false,
73+
extraMemoryLimit: 0,
74+
};
75+
76+
this.CpuSeriesE2SmallLimit = {
77+
allowedCores: [],
78+
minMemPerCore: 2048,
79+
maxMemPerCore: 4096,
80+
allowExtraMemory: false,
81+
extraMemoryLimit: 0,
82+
};
83+
84+
this.CpuSeriesE2MediumLimit = {
85+
allowedCores: [],
86+
minMemPerCore: 4096,
87+
maxMemPerCore: 8192,
88+
allowExtraMemory: false,
89+
extraMemoryLimit: 0,
90+
};
91+
92+
this.CpuSeriesN2Limit = {
93+
allowedCores: [...range(2, 33, 2), ...range(36, 129, 4)],
94+
minMemPerCore: 512,
95+
maxMemPerCore: 8192,
96+
allowExtraMemory: true,
97+
extraMemoryLimit: 624 << 10,
98+
};
99+
100+
this.CpuSeriesN2DLimit = {
101+
allowedCores: [2, 4, 8, 16, 32, 48, 64, 80, 96],
102+
minMemPerCore: 512,
103+
maxMemPerCore: 8192,
104+
allowExtraMemory: true,
105+
extraMemoryLimit: 768 << 10,
106+
};
107+
108+
this.CpuSeriesN1Limit = {
109+
allowedCores: [1, range(2, 97, 2)],
110+
minMemPerCore: 922,
111+
maxMemPerCore: 6656,
112+
allowExtraMemory: true,
113+
extraMemoryLimit: 624 << 10,
114+
};
115+
116+
this.TYPE_LIMITS = {
117+
[this.N1]: this.CpuSeriesN1Limit,
118+
[this.N2]: this.CpuSeriesN2Limit,
119+
[this.N2D]: this.CpuSeriesN2DLimit,
120+
[this.E2]: this.CpuSeriesE2Limit,
121+
[this.E2Micro]: this.CpuSeriesE2MicroLimit,
122+
[this.E2Small]: this.CpuSeriesE2SmallLimit,
123+
[this.E2Medium]: this.CpuSeriesE2MediumLimit,
124+
};
125+
126+
if (![this.E2, this.N1, this.N2, this.N2D].includes(cpuSeries)) {
127+
throw new Error(`Incorrect CPU type: ${this.cpuSeries}`);
128+
}
129+
130+
this.typeLimit = this.TYPE_LIMITS[this.cpuSeries];
131+
132+
// Check whether the requested parameters are allowed.
133+
// Find more information about limitations of custom machine types at:
134+
// https://cloud.google.com/compute/docs/general-purpose-machines#custom_machine_types
135+
136+
// Check the number of cores
137+
if (
138+
this.typeLimit.allowedCores.length > 0 &&
139+
!this.typeLimit.allowedCores.includes(coreCount)
140+
) {
141+
throw new Error(
142+
`Invalid number of cores requested. Allowed number of cores for ${this.cpuSeries} is: ${this.typeLimit.allowedCores}`
143+
);
144+
}
145+
146+
// Memory must be a multiple of 256 MB
147+
if (this.memory % 256 !== 0) {
148+
throw new Error('Requested memory must be a multiple of 256 MB');
149+
}
150+
151+
// Check if the requested memory isn't too little
152+
if (this.memory < this.coreCount * this.typeLimit.minMemPerCore) {
153+
throw new Error(
154+
`Requested memory is too low. Minimal memory for ${this.cpuSeries} is ${this.typeLimit.minMemPerCore} MB per core`
155+
);
156+
}
157+
158+
// Check if the requested memory isn't too much
159+
if (
160+
this.memory > this.coreCount * this.typeLimit.maxMemPerCore &&
161+
!this.typeLimit.allowExtraMemory
162+
) {
163+
throw new Error(
164+
`Requested memory is too large.. Maximum memory allowed for ${this.cpuSeries} is ${this.typeLimit.maxMemPerCore} MB per core`
165+
);
166+
}
167+
168+
if (
169+
this.memory > this.typeLimit.extraMemoryLimit &&
170+
this.typeLimit.allowExtraMemory
171+
) {
172+
throw new Error(
173+
`Requested memory is too large.. Maximum memory allowed for ${this.cpuSeries} is ${this.typeLimit.extraMemoryLimit} MB`
174+
);
175+
}
176+
}
177+
178+
// Returns the custom machine type in form of a string acceptable by Compute Engine API.
179+
getMachineTypeURI() {
180+
if (
181+
[this.E2Small, this.E2Micro, this.E2Medium].includes(this.cpuSeries)
182+
) {
183+
return `zones/${this.zone}/machineTypes/${this.cpuSeries}-${this.memory}`;
184+
}
185+
186+
if (this.memory > this.coreCount * this.typeLimit.maxMemPerCore) {
187+
return `zones/${this.zone}/machineTypes/${this.cpuSeries}-${this.coreCount}-${this.memory}-ext`;
188+
}
189+
190+
return `zones/${zone}/machineTypes/${this.cpuSeries}-${this.coreCount}-${this.memory}`;
191+
}
192+
}
193+
194+
async function createInstanceWithCustomMachineTypeWithHelper() {
195+
const instancesClient = new compute.InstancesClient();
196+
197+
const machineType = new CustomMachineType(
198+
zone,
199+
cpuSeries,
200+
coreCount,
201+
memory
202+
).getMachineTypeURI();
203+
204+
const [response] = await instancesClient.insert({
205+
instanceResource: {
206+
name: instanceName,
207+
disks: [
208+
{
209+
initializeParams: {
210+
diskSizeGb: '64',
211+
sourceImage:
212+
'projects/debian-cloud/global/images/family/debian-11/',
213+
},
214+
autoDelete: true,
215+
boot: true,
216+
},
217+
],
218+
machineType,
219+
networkInterfaces: [
220+
{
221+
name: 'global/networks/default',
222+
},
223+
],
224+
},
225+
project: projectId,
226+
zone,
227+
});
228+
let operation = response.latestResponse;
229+
const operationsClient = new compute.ZoneOperationsClient();
230+
231+
// Wait for the create operation to complete.
232+
while (operation.status !== 'DONE') {
233+
[operation] = await operationsClient.wait({
234+
operation: operation.name,
235+
project: projectId,
236+
zone: operation.zone.split('/').pop(),
237+
});
238+
}
239+
240+
console.log('Instance created.');
241+
}
242+
243+
createInstanceWithCustomMachineTypeWithHelper();
244+
// [END compute_custom_machine_type_create_with_helper]
245+
}
246+
247+
process.on('unhandledRejection', err => {
248+
console.error(err.message);
249+
process.exitCode = 1;
250+
});
251+
252+
const args = process.argv.slice(2);
253+
args[4] = parseInt(args[4]);
254+
args[5] = parseInt(args[5]);
255+
256+
main(...args);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 new VM instances without using a CustomMachineType class.
17+
*
18+
* @param {string} projectId - ID or number of the project you want to use.
19+
* @param {string} zone - Name of the zone you want to use, for example: us-west3-b
20+
* @param {string} instanceName - Name of the new machine.
21+
* @param {string} cpuSeries - Type of CPU you want to use.
22+
* @param {int} coreCount - Number of CPU cores you want to use.
23+
* @param {int} memory - The amount of memory for the VM instance, in megabytes.
24+
*/
25+
function main(projectId, zone, instanceName, cpuSeries, coreCount, memory) {
26+
// [START compute_custom_machine_type_create_without_helper]
27+
/**
28+
* TODO(developer): Uncomment and replace these variables before running the sample.
29+
*/
30+
// const projectId = 'YOUR_PROJECT_ID';
31+
// const zone = 'europe-central2-b';
32+
// const instanceName = 'YOUR_INSTANCE_NAME';
33+
// const cpuSeries = 'N1';
34+
// const coreCount = 2
35+
// const memory = 256
36+
37+
const compute = require('@google-cloud/compute');
38+
39+
async function createWithoutHelper() {
40+
const instancesClient = new compute.InstancesClient();
41+
42+
const machineType = `zones/${zone}/machineTypes/${cpuSeries}-${coreCount}-${memory}`;
43+
44+
const [response] = await instancesClient.insert({
45+
instanceResource: {
46+
name: instanceName,
47+
disks: [
48+
{
49+
initializeParams: {
50+
diskSizeGb: '64',
51+
sourceImage:
52+
'projects/debian-cloud/global/images/family/debian-11/',
53+
},
54+
autoDelete: true,
55+
boot: true,
56+
},
57+
],
58+
machineType,
59+
networkInterfaces: [
60+
{
61+
name: 'global/networks/default',
62+
},
63+
],
64+
},
65+
project: projectId,
66+
zone,
67+
});
68+
let operation = response.latestResponse;
69+
const operationsClient = new compute.ZoneOperationsClient();
70+
71+
// Wait for the create operation to complete.
72+
while (operation.status !== 'DONE') {
73+
[operation] = await operationsClient.wait({
74+
operation: operation.name,
75+
project: projectId,
76+
zone: operation.zone.split('/').pop(),
77+
});
78+
}
79+
80+
console.log('Instance created.');
81+
}
82+
83+
createWithoutHelper();
84+
// [END compute_custom_machine_type_create_without_helper]
85+
}
86+
87+
process.on('unhandledRejection', err => {
88+
console.error(err.message);
89+
process.exitCode = 1;
90+
});
91+
92+
const args = process.argv.slice(2);
93+
args[4] = parseInt(args[4]);
94+
args[5] = parseInt(args[5]);
95+
96+
main(...args);

0 commit comments

Comments
 (0)