package org.ovirt.engine.core.utils.ovf; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.businessentities.ArchitectureType; import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotStatus; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotType; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmDevice; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.utils.customprop.VmPropertiesUtils; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.ovf.xml.XmlDocument; import org.ovirt.engine.core.utils.ovf.xml.XmlNode; import org.ovirt.engine.core.utils.ovf.xml.XmlNodeList; public class OvfVmReader extends OvfReader { private static final String EXPORT_ONLY_PREFIX = "exportonly_"; protected VM _vm; public OvfVmReader(XmlDocument document, VM vm, List<DiskImage> images, List<VmNetworkInterface> interfaces) { super(document, images, interfaces, vm.getStaticData()); _vm = vm; _vm.setInterfaces(interfaces); } @Override protected void readOsSection(XmlNode section) { _vm.getStaticData().setId(new Guid(section.attributes.get("ovf:id").getValue())); XmlNode node = selectSingleNode(section, "Description"); if (node != null) { int osId = osRepository.getOsIdByUniqueName(node.innerText); _vm.getStaticData().setOsId(osId); _vm.setClusterArch(osRepository.getArchitectureFromOS(osId)); } else { _vm.setClusterArch(ArchitectureType.undefined); } } @Override protected void readDiskImageItem(XmlNode node) { final Guid guid = new Guid(selectSingleNode(node, "rasd:InstanceId", _xmlNS).innerText); DiskImage image = _images.stream().filter(d -> d.getImageId().equals(guid)).findFirst().orElse(null); image.setId(OvfParser.getImageGroupIdFromImageFile(selectSingleNode(node, "rasd:HostResource", _xmlNS).innerText)); if (StringUtils.isNotEmpty(selectSingleNode(node, "rasd:Parent", _xmlNS).innerText)) { image.setParentId(new Guid(selectSingleNode(node, "rasd:Parent", _xmlNS).innerText)); } if (StringUtils.isNotEmpty(selectSingleNode(node, "rasd:Template", _xmlNS).innerText)) { image.setImageTemplateId(new Guid(selectSingleNode(node, "rasd:Template", _xmlNS).innerText)); } image.setAppList(selectSingleNode(node, "rasd:ApplicationList", _xmlNS).innerText); XmlNode storageNode = selectSingleNode(node, "rasd:StorageId", _xmlNS); if (storageNode != null && StringUtils.isNotEmpty(storageNode.innerText)) { image.setStorageIds(new ArrayList<>(Arrays.asList(new Guid(storageNode.innerText)))); } if (StringUtils.isNotEmpty(selectSingleNode(node, "rasd:StoragePoolId", _xmlNS).innerText)) { image.setStoragePoolId(new Guid(selectSingleNode(node, "rasd:StoragePoolId", _xmlNS).innerText)); } final Date creationDate = OvfParser.utcDateStringToLocaDate( selectSingleNode(node, "rasd:CreationDate", _xmlNS).innerText); if (creationDate != null) { image.setCreationDate(creationDate); } final Date lastModified = OvfParser.utcDateStringToLocaDate( selectSingleNode(node, "rasd:LastModified", _xmlNS).innerText); if (lastModified != null) { image.setLastModified(lastModified); } final Date last_modified_date = OvfParser.utcDateStringToLocaDate( selectSingleNode(node, "rasd:last_modified_date", _xmlNS).innerText); if (last_modified_date != null) { image.setLastModifiedDate(last_modified_date); } VmDevice readDevice = readManagedVmDevice(node, image.getId()); image.setPlugged(readDevice.isPlugged()); } @Override protected void updateSingleNic(XmlNode node, VmNetworkInterface iface) { super.updateSingleNic(node, iface); iface.setMacAddress((selectSingleNode(node, "rasd:MACAddress", _xmlNS) != null) ? selectSingleNode(node, "rasd:MACAddress", _xmlNS).innerText : ""); } @Override protected void readGeneralData(XmlNode content) { // General Vm XmlNode node = selectSingleNode(content, OvfProperties.NAME); if (node != null) { _vm.getStaticData().setName(node.innerText); name = _vm.getStaticData().getName(); } node = selectSingleNode(content, OvfProperties.TEMPLATE_ID); if (node != null) { if (StringUtils.isNotEmpty(node.innerText)) { _vm.getStaticData().setVmtGuid(new Guid(node.innerText)); } } node = selectSingleNode(content, OvfProperties.TEMPLATE_NAME); if (node != null) { if (StringUtils.isNotEmpty(node.innerText)) { _vm.setVmtName(node.innerText); } } node = selectSingleNode(content, OvfProperties.INSTANCE_TYPE_ID); if (node != null) { if (StringUtils.isNotEmpty(node.innerText)) { _vm.setInstanceTypeId(new Guid(node.innerText)); } } node = selectSingleNode(content, OvfProperties.IMAGE_TYPE_ID); if (node != null) { if (StringUtils.isNotEmpty(node.innerText)) { _vm.setImageTypeId(new Guid(node.innerText)); } } node = selectSingleNode(content, OvfProperties.IS_INITIALIZED); if (node != null) { _vm.getStaticData().setInitialized(Boolean.parseBoolean(node.innerText)); } node = selectSingleNode(content, OvfProperties.QUOTA_ID); if (node != null) { Guid quotaId = new Guid(node.innerText); if (!Guid.Empty.equals(quotaId)) { _vm.getStaticData().setQuotaId(quotaId); } } OvfLogEventHandler<VmStatic> handler = new VMStaticOvfLogHandler(_vm.getStaticData()); // Gets a list of all the aliases of the fields that should be logged in // ovd For each one of these fields, the proper value will be read from // the ovf and field in vm static List<String> aliases = handler.getAliases(); for (String alias : aliases) { String value = readEventLogValue(content, alias); if (StringUtils.isNotEmpty(value)) { handler.addValueForAlias(alias, value); } } // {@link VM#predefinedProperties} and {@link VM#userDefinedProperties} // are being set in the above alias handling, we need to update custom properties // to keep them consistent _vm.setCustomProperties(VmPropertiesUtils.getInstance().customProperties(_vm.getPredefinedProperties(), _vm.getUserDefinedProperties())); node = selectSingleNode(content, OvfProperties.APPLICATIONS_LIST); if (node != null) { if (StringUtils.isNotEmpty(node.innerText)) { _vm.setAppList(node.innerText); } } // if no app list in VM, get it from one of the leafs else if(_images != null && _images.size() > 0) { int root = getFirstImage(_images, _images.get(0)); if (root != -1) { for(int i=0; i<_images.size(); i++) { int x = getNextImage(_images, _images.get(i)); if (x == -1) { _vm.setAppList(_images.get(i).getAppList()); } } } else { _vm.setAppList(_images.get(0).getAppList()); } } node = selectSingleNode(content, OvfProperties.TRUSTED_SERVICE); if (node != null) { _vm.setTrustedService(Boolean.parseBoolean(node.innerText)); } node = selectSingleNode(content, OvfProperties.ORIGINAL_TEMPLATE_ID); if (node != null) { _vm.getStaticData().setOriginalTemplateGuid(new Guid(node.innerText)); } node = selectSingleNode(content, OvfProperties.ORIGINAL_TEMPLATE_NAME); if (node != null) { _vm.getStaticData().setOriginalTemplateName(node.innerText); } node = selectSingleNode(content, OvfProperties.USE_LATEST_VERSION); if (node != null) { _vm.setUseLatestVersion(Boolean.parseBoolean(node.innerText)); } node = selectSingleNode(content, OvfProperties.USE_HOST_CPU); if (node != null) { _vm.setUseHostCpuFlags(Boolean.parseBoolean(node.innerText)); } } @Override protected String getDefaultDisplayTypeStringRepresentation() { return OvfProperties.VM_DEFAULT_DISPLAY_TYPE; } // function returns the index of the image that has no parent private static int getFirstImage(List<DiskImage> images, DiskImage curr) { for (int i = 0; i < images.size(); i++) { if (curr.getParentId().equals(images.get(i).getImageId())) { return i; } } return -1; } // function returns the index of image that is it's child private static int getNextImage(List<DiskImage> images, DiskImage curr) { for (int i = 0; i < images.size(); i++) { if (images.get(i).getParentId().equals(curr.getImageId())) { return i; } } return -1; } private String readEventLogValue(XmlNode content, String name) { StringBuilder fullNameSB = new StringBuilder(EXPORT_ONLY_PREFIX); fullNameSB.append(name); XmlNode node = selectSingleNode(content, fullNameSB.toString()); if (node != null) { return node.innerText; } return null; } @Override protected void readSnapshotsSection(XmlNode section) { XmlNodeList list = selectNodes(section, "Snapshot"); List<Snapshot> snapshots = new ArrayList<>(); _vm.setSnapshots(snapshots); for (XmlNode node : list) { XmlNode vmConfiguration = selectSingleNode(node, "VmConfiguration", _xmlNS); Snapshot snapshot = new Snapshot(vmConfiguration != null); snapshot.setId(new Guid(node.attributes.get("ovf:id").getValue())); snapshot.setVmId(_vm.getId()); snapshot.setType(SnapshotType.valueOf(selectSingleNode(node, "Type", _xmlNS).innerText)); snapshot.setStatus(SnapshotStatus.OK); snapshot.setDescription(selectSingleNode(node, "Description", _xmlNS).innerText); XmlNode memory = selectSingleNode(node, "Memory", _xmlNS); if (memory != null) { snapshot.setMemoryVolume(memory.innerText); } final Date creationDate = OvfParser.utcDateStringToLocaDate(selectSingleNode(node, "CreationDate", _xmlNS).innerText); if (creationDate != null) { snapshot.setCreationDate(creationDate); } snapshot.setVmConfiguration(vmConfiguration == null ? null : new String(Base64.decodeBase64(vmConfiguration.innerText))); XmlNode appList = selectSingleNode(node, "ApplicationList", _xmlNS); if (appList != null) { snapshot.setAppList(appList.innerText); } snapshots.add(snapshot); } } @Override protected void buildNicReference() { } }