1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.writeOvaOn = writeOvaOn;
|
7 | var _tarStream = _interopRequireDefault(require("tar-stream"));
|
8 | var _ = require(".");
|
9 | var _promiseToolbox = require("promise-toolbox");
|
10 | var _stream = require("stream");
|
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
12 | async function writeOvaOn(outStream, {
|
13 | vmName,
|
14 | vmDescription = '',
|
15 | disks = [],
|
16 | firmware = 'bios',
|
17 | nics = [],
|
18 | vmMemoryMB = 64,
|
19 | cpuCount = 1
|
20 | }) {
|
21 | const ovf = createOvf(vmName, vmDescription, disks, nics, vmMemoryMB, cpuCount, firmware);
|
22 | const tarStream = _tarStream.default.pack();
|
23 | (0, _stream.pipeline)(tarStream, outStream, () => {});
|
24 | await _promiseToolbox.fromCallback.call(tarStream, tarStream.entry, {
|
25 | name: `metadata.ovf`
|
26 | }, Buffer.from(ovf, 'utf8'));
|
27 | async function pushDisk(disk) {
|
28 | let {
|
29 | iterator,
|
30 | size
|
31 | } = await (0, _.vhdToVMDKIterator)(disk.name, await disk.getStream());
|
32 | if (size === undefined) {
|
33 | size = await (0, _.computeVmdkLength)(disk.name, await disk.getStream());
|
34 | }
|
35 | disk.fileSize = size;
|
36 | return new Promise((resolve, reject) => {
|
37 | const entryWriteStream = tarStream.entry({
|
38 | name: `${disk.name}.vmdk`,
|
39 | size,
|
40 | type: 'file'
|
41 | }, err => {
|
42 | if (err == null) {
|
43 | return resolve();
|
44 | } else return reject(err);
|
45 | });
|
46 | (0, _stream.pipeline)(iterator, entryWriteStream, () => {});
|
47 | });
|
48 | }
|
49 | for (const disk of disks) {
|
50 | await pushDisk(disk);
|
51 | }
|
52 | tarStream.finalize();
|
53 | return outStream;
|
54 | }
|
55 | function createDiskSections(disks) {
|
56 | const fileReferences = [];
|
57 | const diskFragments = [];
|
58 | const diskItems = [];
|
59 | for (let i = 0; i < disks.length; i++) {
|
60 | const disk = disks[i];
|
61 | const diskId = `vmdisk${i + 1}`;
|
62 | fileReferences.push(` <File ovf:href="${disk.fileName}" ovf:id="file${i + 1}"/>`);
|
63 | diskFragments.push(` <Disk ovf:capacity="${disk.capacityMB}" ovf:capacityAllocationUnits="byte * 2^20" ovf:diskId="${diskId}" ovf:fileRef="file${i + 1}" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" />`);
|
64 | diskItems.push(`
|
65 | <Item>
|
66 | <rasd:AddressOnParent>${i}</rasd:AddressOnParent>
|
67 | <rasd:ElementName>Hard Disk ${i + 1}</rasd:ElementName>
|
68 | <rasd:HostResource>ovf:/disk/${diskId}</rasd:HostResource>
|
69 | <rasd:InstanceID>${diskId}</rasd:InstanceID>
|
70 | <rasd:Parent>4</rasd:Parent>
|
71 | <rasd:ResourceType>17</rasd:ResourceType>
|
72 | </Item>
|
73 | `);
|
74 | }
|
75 | return {
|
76 | fileReferences: fileReferences.join('\n'),
|
77 | diskFragments: diskFragments.join('\n'),
|
78 | diskItems: diskItems.join('\n')
|
79 | };
|
80 | }
|
81 | function createNicsSection(nics) {
|
82 | const networks = new Set();
|
83 | const nicItems = [];
|
84 | for (let i = 0; i < nics.length; i++) {
|
85 | const nic = nics[i];
|
86 | networks.add(nic.networkName);
|
87 | const text = `
|
88 | <Item>
|
89 | <rasd:AddressOnParent>${i}</rasd:AddressOnParent>
|
90 | <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
|
91 | <rasd:Connection>${nic.networkName}</rasd:Connection>
|
92 | <rasd:Description>PCNet32 ethernet adapter on "${nic.networkName}"</rasd:Description>
|
93 | <rasd:ElementName>Connection to ${nic.networkName}</rasd:ElementName>
|
94 | <rasd:InstanceID>${'nic' + i}</rasd:InstanceID>
|
95 | <rasd:ResourceSubType>PCNet32</rasd:ResourceSubType>
|
96 | <rasd:ResourceType>10</rasd:ResourceType>
|
97 | </Item>
|
98 | `;
|
99 | nicItems.push(text);
|
100 | }
|
101 | const networksElements = [];
|
102 | for (const network of networks) {
|
103 | networksElements.push(` <Network ovf:name="${network}"/>`);
|
104 | }
|
105 | return {
|
106 | nicsSection: nicItems.join('\n'),
|
107 | networksSection: networksElements.join('\n')
|
108 | };
|
109 | }
|
110 | function createOvf(vmName, vmDescription, disks = [], nics = [], vmMemoryMB = 64, cpuCount = 1, firmware = 'bios') {
|
111 | const diskSection = createDiskSections(disks);
|
112 | const networkSection = createNicsSection(nics);
|
113 | let id = 1;
|
114 | const nextId = () => id++;
|
115 | return `<?xml version="1.0" encoding="UTF-8"?>
|
116 | <!--Generated by Xen Orchestra-->
|
117 | <ovf:Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
|
118 | xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
|
119 | xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">
|
120 | <References>
|
121 | ${diskSection.fileReferences}
|
122 | </References>
|
123 | <DiskSection>
|
124 | <Info>Virtual disk information</Info>
|
125 | ${diskSection.diskFragments}
|
126 | </DiskSection>
|
127 | <NetworkSection>
|
128 | <Info>The list of logical networks</Info>
|
129 | ${networkSection.networksSection}
|
130 | </NetworkSection>
|
131 | <VirtualSystem ovf:id="${vmName}">
|
132 | <Info>A virtual machine</Info>
|
133 | <Name>${vmName}</Name>
|
134 | <OperatingSystemSection ovf:id="${nextId()}">
|
135 | <Info>The kind of installed guest operating system</Info>
|
136 | </OperatingSystemSection>
|
137 | <VirtualHardwareSection>
|
138 | <Info>Virtual hardware requirements</Info>
|
139 | <System>
|
140 | <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
|
141 | <vssd:InstanceID>0</vssd:InstanceID>
|
142 | <vssd:VirtualSystemIdentifier>${vmName}</vssd:VirtualSystemIdentifier>
|
143 | <vssd:VirtualSystemType>vmx-11</vssd:VirtualSystemType>
|
144 | </System>
|
145 | <Item>
|
146 | <rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
|
147 | <rasd:Description>Number of Virtual CPUs</rasd:Description>
|
148 | <rasd:ElementName>${cpuCount} virtual CPU(s)</rasd:ElementName>
|
149 | <rasd:InstanceID>1</rasd:InstanceID>
|
150 | <rasd:ResourceType>3</rasd:ResourceType>
|
151 | <rasd:VirtualQuantity>${cpuCount}</rasd:VirtualQuantity>
|
152 | </Item>
|
153 | <Item>
|
154 | <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
|
155 | <rasd:Description>Memory Size</rasd:Description>
|
156 | <rasd:ElementName>${vmMemoryMB}MB of memory</rasd:ElementName>
|
157 | <rasd:InstanceID>2</rasd:InstanceID>
|
158 | <rasd:ResourceType>4</rasd:ResourceType>
|
159 | <rasd:VirtualQuantity>${vmMemoryMB}</rasd:VirtualQuantity>
|
160 | </Item>
|
161 | <Item>
|
162 | <rasd:Address>0</rasd:Address>
|
163 | <rasd:Description>IDE Controller</rasd:Description>
|
164 | <rasd:ElementName>VirtualIDEController 0</rasd:ElementName>
|
165 | <rasd:InstanceID>4</rasd:InstanceID>
|
166 | <rasd:ResourceType>5</rasd:ResourceType>
|
167 | </Item>
|
168 | <Item ovf:required="false">
|
169 | <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
|
170 | <rasd:ElementName>VirtualVideoCard</rasd:ElementName>
|
171 | <rasd:InstanceID>5</rasd:InstanceID>
|
172 | <rasd:ResourceType>24</rasd:ResourceType>
|
173 | </Item>
|
174 | ${diskSection.diskItems}
|
175 | ${networkSection.nicsSection}
|
176 | </VirtualHardwareSection>
|
177 | <AnnotationSection ovf:required="false">
|
178 | <Info>A human-readable annotation</Info>
|
179 | <Annotation>${vmDescription}</Annotation>
|
180 | </AnnotationSection>
|
181 | </VirtualSystem>
|
182 | </ovf:Envelope>`;
|
183 | }
|
184 |
|
\ | No newline at end of file |