xo-vmdk-to-vhd
Version:
JS lib reading and writing .vmdk and .ova files
184 lines (183 loc) • 6.95 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.writeOvaOn = writeOvaOn;
var _tarStream = _interopRequireDefault(require("tar-stream"));
var _ = require(".");
var _promiseToolbox = require("promise-toolbox");
var _stream = require("stream");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
async function writeOvaOn(outStream, {
vmName,
vmDescription = '',
disks = [],
firmware = 'bios',
nics = [],
vmMemoryMB = 64,
cpuCount = 1
}) {
const ovf = createOvf(vmName, vmDescription, disks, nics, vmMemoryMB, cpuCount, firmware);
const tarStream = _tarStream.default.pack();
(0, _stream.pipeline)(tarStream, outStream, () => {});
await _promiseToolbox.fromCallback.call(tarStream, tarStream.entry, {
name: `metadata.ovf`
}, Buffer.from(ovf, 'utf8'));
async function pushDisk(disk) {
let {
iterator,
size
} = await (0, _.vhdToVMDKIterator)(disk.name, await disk.getStream());
if (size === undefined) {
size = await (0, _.computeVmdkLength)(disk.name, await disk.getStream());
}
disk.fileSize = size;
return new Promise((resolve, reject) => {
const entryWriteStream = tarStream.entry({
name: `${disk.name}.vmdk`,
size,
type: 'file'
}, err => {
if (err == null) {
return resolve();
} else return reject(err);
});
(0, _stream.pipeline)(iterator, entryWriteStream, () => {});
});
}
for (const disk of disks) {
await pushDisk(disk);
}
tarStream.finalize();
return outStream;
}
function createDiskSections(disks) {
const fileReferences = [];
const diskFragments = [];
const diskItems = [];
for (let i = 0; i < disks.length; i++) {
const disk = disks[i];
const diskId = `vmdisk${i + 1}`;
fileReferences.push(` <File ovf:href="${disk.fileName}" ovf:id="file${i + 1}"/>`);
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" />`);
diskItems.push(`
<Item>
<rasd:AddressOnParent>${i}</rasd:AddressOnParent>
<rasd:ElementName>Hard Disk ${i + 1}</rasd:ElementName>
<rasd:HostResource>ovf:/disk/${diskId}</rasd:HostResource>
<rasd:InstanceID>${diskId}</rasd:InstanceID>
<rasd:Parent>4</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item>
`);
}
return {
fileReferences: fileReferences.join('\n'),
diskFragments: diskFragments.join('\n'),
diskItems: diskItems.join('\n')
};
}
function createNicsSection(nics) {
const networks = new Set();
const nicItems = [];
for (let i = 0; i < nics.length; i++) {
const nic = nics[i];
networks.add(nic.networkName);
const text = `
<Item>
<rasd:AddressOnParent>${i}</rasd:AddressOnParent>
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
<rasd:Connection>${nic.networkName}</rasd:Connection>
<rasd:Description>PCNet32 ethernet adapter on "${nic.networkName}"</rasd:Description>
<rasd:ElementName>Connection to ${nic.networkName}</rasd:ElementName>
<rasd:InstanceID>${'nic' + i}</rasd:InstanceID>
<rasd:ResourceSubType>PCNet32</rasd:ResourceSubType>
<rasd:ResourceType>10</rasd:ResourceType>
</Item>
`;
nicItems.push(text);
}
const networksElements = [];
for (const network of networks) {
networksElements.push(` <Network ovf:name="${network}"/>`);
}
return {
nicsSection: nicItems.join('\n'),
networksSection: networksElements.join('\n')
};
}
function createOvf(vmName, vmDescription, disks = [], nics = [], vmMemoryMB = 64, cpuCount = 1, firmware = 'bios') {
const diskSection = createDiskSections(disks);
const networkSection = createNicsSection(nics);
let id = 1;
const nextId = () => id++;
return `
<!--Generated by Xen Orchestra-->
<ovf:Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">
<References>
${diskSection.fileReferences}
</References>
<DiskSection>
<Info>Virtual disk information</Info>
${diskSection.diskFragments}
</DiskSection>
<NetworkSection>
<Info>The list of logical networks</Info>
${networkSection.networksSection}
</NetworkSection>
<VirtualSystem ovf:id="${vmName}">
<Info>A virtual machine</Info>
<Name>${vmName}</Name>
<OperatingSystemSection ovf:id="${nextId()}">
<Info>The kind of installed guest operating system</Info>
</OperatingSystemSection>
<VirtualHardwareSection>
<Info>Virtual hardware requirements</Info>
<System>
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
<vssd:InstanceID>0</vssd:InstanceID>
<vssd:VirtualSystemIdentifier>${vmName}</vssd:VirtualSystemIdentifier>
<vssd:VirtualSystemType>vmx-11</vssd:VirtualSystemType>
</System>
<Item>
<rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
<rasd:Description>Number of Virtual CPUs</rasd:Description>
<rasd:ElementName>${cpuCount} virtual CPU(s)</rasd:ElementName>
<rasd:InstanceID>1</rasd:InstanceID>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>${cpuCount}</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
<rasd:Description>Memory Size</rasd:Description>
<rasd:ElementName>${vmMemoryMB}MB of memory</rasd:ElementName>
<rasd:InstanceID>2</rasd:InstanceID>
<rasd:ResourceType>4</rasd:ResourceType>
<rasd:VirtualQuantity>${vmMemoryMB}</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Description>IDE Controller</rasd:Description>
<rasd:ElementName>VirtualIDEController 0</rasd:ElementName>
<rasd:InstanceID>4</rasd:InstanceID>
<rasd:ResourceType>5</rasd:ResourceType>
</Item>
<Item ovf:required="false">
<rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
<rasd:ElementName>VirtualVideoCard</rasd:ElementName>
<rasd:InstanceID>5</rasd:InstanceID>
<rasd:ResourceType>24</rasd:ResourceType>
</Item>
${diskSection.diskItems}
${networkSection.nicsSection}
</VirtualHardwareSection>
<AnnotationSection ovf:required="false">
<Info>A human-readable annotation</Info>
<Annotation>${vmDescription}</Annotation>
</AnnotationSection>
</VirtualSystem>
</ovf:Envelope>`;
}
//# sourceMappingURL=ova-generate.js.map