Skip to content

Commit dae1ca0

Browse files
committed
Deploy OVF from configuation ID into primary storage
1 parent be1f403 commit dae1ca0

File tree

69 files changed

+661
-460
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+661
-460
lines changed

api/src/main/java/com/cloud/agent/api/storage/OVFConfigurationTO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class OVFConfigurationTO {
2929
private int index;
3030

3131
public OVFConfigurationTO(String id, String label, String description, int index) {
32-
this.id = id.toLowerCase();
32+
this.id = id;
3333
this.label = label;
3434
this.description = description;
3535
this.index = index;

api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java

Lines changed: 118 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.io.StringReader;
2323
import java.io.StringWriter;
2424
import java.util.ArrayList;
25+
import java.util.Arrays;
2526
import java.util.Collections;
2627
import java.util.HashMap;
2728
import java.util.LinkedList;
@@ -229,93 +230,127 @@ protected List<OVFEulaSectionTO> getOVFEulaSectionFromXmlString(final String ovf
229230
return getEulaSectionsFromDocument(doc);
230231
}
231232

232-
public List<DatadiskTO> getOVFVolumeInfoFromFile(final String ovfFilePath) throws InternalErrorException {
233+
public List<DatadiskTO> getOVFVolumeInfoFromFile(final String ovfFilePath, final String configurationId) throws InternalErrorException {
233234
if (StringUtils.isBlank(ovfFilePath)) {
234235
return new ArrayList<>();
235236
}
236237
Document doc = getDocumentFromFile(ovfFilePath);
237238

238-
return getOVFVolumeInfoFromFile(ovfFilePath, doc);
239+
return getOVFVolumeInfoFromFile(ovfFilePath, doc, configurationId);
239240
}
240241

241-
public List<DatadiskTO> getOVFVolumeInfoFromFile(String ovfFilePath, Document doc) throws InternalErrorException {
242+
public List<DatadiskTO> getOVFVolumeInfoFromFile(String ovfFilePath, Document doc, String configurationId) throws InternalErrorException {
242243
if (org.apache.commons.lang.StringUtils.isBlank(ovfFilePath)) {
243244
return null;
244245
}
245246

246247
File ovfFile = new File(ovfFilePath);
247-
NodeList disks = doc.getElementsByTagName("Disk");
248-
NodeList files = doc.getElementsByTagName("File");
249-
NodeList items = doc.getElementsByTagName("Item");
250-
List<OVFFile> vf = extractFilesFromOvfDocumentTree(ovfFile, files);
251-
252-
List<OVFDisk> vd = extractDisksFromOvfDocumentTree(disks, items);
253-
254-
List<DatadiskTO> diskTOs = matchDisksToFilesAndGenerateDiskTOs(ovfFile, vf, vd);
255-
256-
moveFirstIsoToEndOfDiskList(diskTOs);
257-
248+
List<OVFVirtualHardwareItemTO> hardwareItems = getVirtualHardwareItemsFromDocumentTree(doc);
249+
List<OVFFile> files = extractFilesFromOvfDocumentTree(ovfFile, doc);
250+
List<OVFDisk> disks = extractDisksFromOvfDocumentTree(doc);
251+
252+
List<OVFVirtualHardwareItemTO> diskHardwareItems = hardwareItems.stream()
253+
.filter(x -> x.getResourceType() == OVFVirtualHardwareItemTO.HardwareResourceType.DiskDrive &&
254+
hardwareItemContainsConfiguration(x, configurationId))
255+
.collect(Collectors.toList());
256+
List<DatadiskTO> diskTOs = matchHardwareItemsToDiskAndFilesInformation(diskHardwareItems, files, disks, ovfFile.getParent());
258257
return diskTOs;
259258
}
260259

261-
/**
262-
* check if first disk is an iso move it to the end. the semantics of this are not complete as more than one ISO may be there and theoretically an OVA may only contain ISOs
263-
*
264-
*/
265-
private void moveFirstIsoToEndOfDiskList(List<DatadiskTO> diskTOs) {
266-
if (CollectionUtils.isNotEmpty(diskTOs)) {
267-
DatadiskTO fd = diskTOs.get(0);
268-
if (fd.isIso()) {
269-
if (s_logger.isDebugEnabled()) {
270-
s_logger.debug("moving first disk to the end as it is an ISO");
271-
}
272-
diskTOs.remove(0);
273-
diskTOs.add(fd);
260+
private String extractDiskIdFromDiskHostResource(String hostResource) {
261+
if (hostResource.startsWith("ovf:/disk/")) {
262+
return hostResource.replace("ovf:/disk/", "");
263+
}
264+
String[] resourceParts = hostResource.split("/");
265+
return resourceParts[resourceParts.length - 1];
266+
}
267+
268+
private OVFDisk getDiskDefinitionFromDiskId(String diskId, List<OVFDisk> disks) {
269+
for (OVFDisk disk : disks) {
270+
if (disk._diskId.equalsIgnoreCase(diskId)) {
271+
return disk;
274272
}
275273
}
274+
return null;
276275
}
277276

278-
private List<DatadiskTO> matchDisksToFilesAndGenerateDiskTOs(File ovfFile, List<OVFFile> vf, List<OVFDisk> vd) throws InternalErrorException {
279-
List<DatadiskTO> diskTOs = new ArrayList<>();
277+
private List<DatadiskTO> matchHardwareItemsToDiskAndFilesInformation(List<OVFVirtualHardwareItemTO> diskHardwareItems,
278+
List<OVFFile> files, List<OVFDisk> disks,
279+
String ovfParentPath) throws InternalErrorException {
280+
List<DatadiskTO> diskTOs = new LinkedList<>();
280281
int diskNumber = 0;
281-
for (OVFFile of : vf) {
282-
if (StringUtils.isBlank(of._id)){
283-
s_logger.error("The ovf file info is incomplete file info");
284-
throw new InternalErrorException("The ovf file info has incomplete file info");
285-
}
286-
OVFDisk cdisk = getDisk(of._id, vd);
287-
if (cdisk == null && !of.isIso){
288-
s_logger.error("The ovf file info has incomplete disk info");
289-
throw new InternalErrorException("The ovf file info has incomplete disk info");
282+
for (OVFVirtualHardwareItemTO diskItem : diskHardwareItems) {
283+
if (StringUtils.isBlank(diskItem.getHostResource())) {
284+
s_logger.error("Missing disk information for hardware item " + diskItem.getElementName() + " " + diskItem.getInstanceId());
285+
continue;
290286
}
291-
Long capacity = cdisk == null ? of._size : cdisk._capacity;
292-
String controller = "";
293-
String controllerSubType = "";
294-
if (cdisk != null) {
295-
OVFDiskController cDiskController = cdisk._controller;
296-
controller = cDiskController == null ? "" : cdisk._controller._name;
297-
controllerSubType = cDiskController == null ? "" : cdisk._controller._subType;
287+
String diskId = extractDiskIdFromDiskHostResource(diskItem.getHostResource());
288+
OVFDisk diskDefinition = getDiskDefinitionFromDiskId(diskId, disks);
289+
if (diskDefinition == null) {
290+
s_logger.error("Missing disk definition for disk ID " + diskId);
298291
}
292+
OVFFile fileDefinition = getFileDefinitionFromDiskDefinition(diskDefinition._fileRef, files);
293+
DatadiskTO datadiskTO = generateDiskTO(fileDefinition, diskDefinition, ovfParentPath, diskNumber, diskItem);
294+
diskTOs.add(datadiskTO);
295+
diskNumber++;
296+
}
297+
List<OVFFile> isoFiles = files.stream().filter(x -> x.isIso).collect(Collectors.toList());
298+
for (OVFFile isoFile : isoFiles) {
299+
DatadiskTO isoTO = generateDiskTO(isoFile, null, ovfParentPath, diskNumber, null);
300+
diskTOs.add(isoTO);
301+
diskNumber++;
302+
}
303+
return diskTOs;
304+
}
299305

300-
String dataDiskPath = ovfFile.getParent() + File.separator + of._href;
301-
File f = new File(dataDiskPath);
306+
private DatadiskTO generateDiskTO(OVFFile file, OVFDisk disk, String ovfParentPath, int diskNumber,
307+
OVFVirtualHardwareItemTO diskItem) throws InternalErrorException {
308+
String path = file != null ? ovfParentPath + File.separator + file._href : null;
309+
if (StringUtils.isNotBlank(path)) {
310+
File f = new File(path);
302311
if (!f.exists() || f.isDirectory()) {
303-
s_logger.error("One of the attached disk or iso does not exists " + dataDiskPath);
304-
throw new InternalErrorException("One of the attached disk or iso as stated on OVF does not exists " + dataDiskPath);
312+
s_logger.error("One of the attached disk or iso does not exists " + path);
313+
throw new InternalErrorException("One of the attached disk or iso as stated on OVF does not exists " + path);
305314
}
306-
diskTOs.add(new DatadiskTO(dataDiskPath, capacity, of._size, of._id, of.isIso, of._bootable, controller, controllerSubType, diskNumber));
307-
diskNumber++;
308315
}
309-
if (s_logger.isTraceEnabled()) {
310-
s_logger.trace(String.format("found %d file definitions in %s",diskTOs.size(), ovfFile.getPath()));
316+
Long capacity = disk != null ? disk._capacity : file._size;
317+
Long fileSize = file != null ? file._size : 0L;
318+
319+
String controller = "";
320+
String controllerSubType = "";
321+
if (disk != null) {
322+
OVFDiskController cDiskController = disk._controller;
323+
controller = cDiskController == null ? "" : disk._controller._name;
324+
controllerSubType = cDiskController == null ? "" : disk._controller._subType;
311325
}
312-
return diskTOs;
326+
327+
boolean isIso = file != null && file.isIso;
328+
boolean bootable = file != null && file._bootable;
329+
String diskId = disk == null ? file._id : disk._diskId;
330+
String configuration = diskItem != null ? diskItem.getConfigurationIds() : null;
331+
return new DatadiskTO(path, capacity, fileSize, diskId,
332+
isIso, bootable, controller, controllerSubType, diskNumber, configuration);
313333
}
314334

315-
private List<OVFDisk> extractDisksFromOvfDocumentTree(NodeList disks, NodeList items) {
335+
protected List<OVFDisk> extractDisksFromOvfDocumentTree(Document doc) {
336+
NodeList disks = doc.getElementsByTagName("Disk");
337+
NodeList ovfDisks = doc.getElementsByTagName("ovf:Disk");
338+
NodeList items = doc.getElementsByTagName("Item");
339+
340+
int totalDisksLength = disks.getLength() + ovfDisks.getLength();
316341
ArrayList<OVFDisk> vd = new ArrayList<>();
317-
for (int i = 0; i < disks.getLength(); i++) {
318-
Element disk = (Element)disks.item(i);
342+
for (int i = 0; i < totalDisksLength; i++) {
343+
Element disk;
344+
if (i >= disks.getLength()) {
345+
int pos = i - disks.getLength();
346+
disk = (Element) ovfDisks.item(pos);
347+
} else {
348+
disk = (Element) disks.item(i);
349+
}
350+
351+
if (disk == null) {
352+
continue;
353+
}
319354
OVFDisk od = new OVFDisk();
320355
String virtualSize = getNodeAttribute(disk, "ovf", "capacity");
321356
od._capacity = NumberUtils.toLong(virtualSize, 0L);
@@ -344,7 +379,8 @@ private List<OVFDisk> extractDisksFromOvfDocumentTree(NodeList disks, NodeList i
344379
return vd;
345380
}
346381

347-
private List<OVFFile> extractFilesFromOvfDocumentTree( File ovfFile, NodeList files) {
382+
protected List<OVFFile> extractFilesFromOvfDocumentTree(File ovfFile, Document doc) {
383+
NodeList files = doc.getElementsByTagName("File");
348384
ArrayList<OVFFile> vf = new ArrayList<>();
349385
boolean toggle = true;
350386
for (int j = 0; j < files.getLength(); j++) {
@@ -528,10 +564,10 @@ private void writeDocumentToFile(String newOvfFilePath, Document doc) {
528564
}
529565
}
530566

531-
OVFDisk getDisk(String fileRef, List<OVFDisk> disks) {
532-
for (OVFDisk disk : disks) {
533-
if (disk._fileRef.equals(fileRef)) {
534-
return disk;
567+
OVFFile getFileDefinitionFromDiskDefinition(String fileRef, List<OVFFile> files) {
568+
for (OVFFile file : files) {
569+
if (file._id.equals(fileRef)) {
570+
return file;
535571
}
536572
}
537573
return null;
@@ -653,6 +689,19 @@ private Map<String, NetworkPrerequisiteTO> getNetworksFromDocumentTree(Document
653689
return nets;
654690
}
655691

692+
private boolean hardwareItemContainsConfiguration(OVFVirtualHardwareItemTO item, String configurationId) {
693+
if (StringUtils.isBlank(configurationId) || StringUtils.isBlank(item.getConfigurationIds())) {
694+
return true;
695+
}
696+
String configurationIds = item.getConfigurationIds();
697+
if (StringUtils.isNotBlank(configurationIds)) {
698+
String[] configurations = configurationIds.split(" ");
699+
List<String> confList = Arrays.asList(configurations);
700+
return confList.contains(configurationId);
701+
}
702+
return false;
703+
}
704+
656705
/**
657706
* Retrieve the virtual hardware section and its deployment options as configurations
658707
*/
@@ -663,7 +712,7 @@ public OVFVirtualHardwareSectionTO getVirtualHardwareSectionFromDocument(Documen
663712
for (OVFConfigurationTO configuration : configurations) {
664713
List<OVFVirtualHardwareItemTO> confItems = items.stream().
665714
filter(x -> StringUtils.isNotBlank(x.getConfigurationIds())
666-
&& x.getConfigurationIds().toLowerCase().contains(configuration.getId()))
715+
&& hardwareItemContainsConfiguration(x, configuration.getId()))
667716
.collect(Collectors.toList());
668717
configuration.setHardwareItems(confItems);
669718
}
@@ -726,6 +775,9 @@ private List<OVFVirtualHardwareItemTO> getVirtualHardwareItemsFromDocumentTree(D
726775
String reservation = getChildNodeValue(configuration, "Reservation");
727776
String resourceType = getChildNodeValue(configuration, "ResourceType");
728777
String virtualQuantity = getChildNodeValue(configuration, "VirtualQuantity");
778+
String hostResource = getChildNodeValue(configuration, "HostResource");
779+
String addressOnParent = getChildNodeValue(configuration, "AddressOnParent");
780+
String parent = getChildNodeValue(configuration, "Parent");
729781
OVFVirtualHardwareItemTO item = new OVFVirtualHardwareItemTO();
730782
item.setConfigurationIds(configurationIds);
731783
item.setAllocationUnits(allocationUnits);
@@ -739,6 +791,9 @@ private List<OVFVirtualHardwareItemTO> getVirtualHardwareItemsFromDocumentTree(D
739791
item.setResourceType(OVFVirtualHardwareItemTO.getResourceTypeFromId(resType));
740792
}
741793
item.setVirtualQuantity(getLongValueFromString(virtualQuantity));
794+
item.setHostResource(hostResource);
795+
item.setAddressOnParent(addressOnParent);
796+
item.setParent(parent);
742797
items.add(item);
743798
}
744799
}
@@ -822,7 +877,6 @@ class OVFDisk {
822877
//<Disk ovf:capacity="50" ovf:capacityAllocationUnits="byte * 2^20" ovf:diskId="vmdisk2" ovf:fileRef="file2"
823878
//ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" ovf:populatedSize="43319296" />
824879
public Long _capacity;
825-
public String _capacityUnit;
826880
public String _diskId;
827881
public String _fileRef;
828882
public Long _populatedSize;

api/src/main/java/com/cloud/agent/api/to/DatadiskTO.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,13 @@ public class DatadiskTO {
2828
private String diskController;
2929
private String diskControllerSubType;
3030
private int diskNumber;
31+
private String configuration;
3132

3233
public DatadiskTO() {
3334
}
3435

35-
public DatadiskTO(String path, long virtualSize, long fileSize, boolean bootable) {
36-
this.path = path;
37-
this.virtualSize = virtualSize;
38-
this.fileSize = fileSize;
39-
this.bootable = bootable;
40-
}
41-
4236
public DatadiskTO(String path, long virtualSize, long fileSize, String diskId, boolean isIso, boolean bootable,
43-
String controller, String controllerSubType, int diskNumber) {
37+
String controller, String controllerSubType, int diskNumber, String configuration) {
4438
this.path = path;
4539
this.virtualSize = virtualSize;
4640
this.fileSize = fileSize;
@@ -50,6 +44,7 @@ public DatadiskTO(String path, long virtualSize, long fileSize, String diskId, b
5044
this.diskController = controller;
5145
this.diskControllerSubType = controllerSubType;
5246
this.diskNumber = diskNumber;
47+
this.configuration = configuration;
5348
}
5449

5550
public String getPath() {
@@ -111,4 +106,8 @@ public void setDiskControllerSubType(String diskControllerSubType) {
111106
public int getDiskNumber() {
112107
return this.diskNumber;
113108
}
109+
110+
public String getConfiguration() {
111+
return configuration;
112+
}
114113
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.api.to;
18+
19+
public class DeployAsIsInfoTO {
20+
21+
private boolean deployAsIs;
22+
private String templatePath;
23+
private String deploymentConfiguration;
24+
25+
public DeployAsIsInfoTO() {
26+
}
27+
28+
public boolean isDeployAsIs() {
29+
return deployAsIs;
30+
}
31+
32+
public void setDeployAsIs(boolean deployAsIs) {
33+
this.deployAsIs = deployAsIs;
34+
}
35+
36+
public String getTemplatePath() {
37+
return templatePath;
38+
}
39+
40+
public void setTemplatePath(String templateInSecondaryPath) {
41+
this.templatePath = templateInSecondaryPath;
42+
}
43+
44+
public String getDeploymentConfiguration() {
45+
return deploymentConfiguration;
46+
}
47+
48+
public void setDeploymentConfiguration(String deploymentConfiguration) {
49+
this.deploymentConfiguration = deploymentConfiguration;
50+
}
51+
}

0 commit comments

Comments
 (0)