Add new template and vm deploy as is details table and refactor

This commit is contained in:
nvazquez 2020-09-14 10:34:01 -03:00 committed by Harikrishna Patnala
parent fab6b41c90
commit bb4ce2118d
45 changed files with 1190 additions and 630 deletions

View File

@ -39,10 +39,15 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import com.cloud.agent.api.to.deployasis.OVFConfigurationTO;
import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareItemTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.Resource.ResourceType;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.utils.compression.CompressionUtil; import com.cloud.utils.compression.CompressionUtil;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
@ -573,7 +578,7 @@ public class OVFHelper {
return null; return null;
} }
public List<NetworkPrerequisiteTO> getNetPrerequisitesFromDocument(Document doc) throws InternalErrorException { public List<OVFNetworkTO> getNetPrerequisitesFromDocument(Document doc) throws InternalErrorException {
if (doc == null) { if (doc == null) {
if (s_logger.isTraceEnabled()) { if (s_logger.isTraceEnabled()) {
s_logger.trace("no document to parse; returning no prerequiste networks"); s_logger.trace("no document to parse; returning no prerequiste networks");
@ -581,7 +586,7 @@ public class OVFHelper {
return Collections.emptyList(); return Collections.emptyList();
} }
Map<String, NetworkPrerequisiteTO> nets = getNetworksFromDocumentTree(doc); Map<String, OVFNetworkTO> nets = getNetworksFromDocumentTree(doc);
checkForOnlyOneSystemNode(doc); checkForOnlyOneSystemNode(doc);
@ -590,7 +595,7 @@ public class OVFHelper {
return new ArrayList<>(nets.values()); return new ArrayList<>(nets.values());
} }
private void matchNicsToNets(Map<String, NetworkPrerequisiteTO> nets, Node systemElement) { private void matchNicsToNets(Map<String, OVFNetworkTO> nets, Node systemElement) {
final DocumentTraversal traversal = (DocumentTraversal) systemElement; final DocumentTraversal traversal = (DocumentTraversal) systemElement;
final NodeIterator iterator = traversal.createNodeIterator(systemElement, NodeFilter.SHOW_ELEMENT, null, true); final NodeIterator iterator = traversal.createNodeIterator(systemElement, NodeFilter.SHOW_ELEMENT, null, true);
if (s_logger.isTraceEnabled()) { if (s_logger.isTraceEnabled()) {
@ -606,9 +611,9 @@ public class OVFHelper {
if(s_logger.isInfoEnabled()) { if(s_logger.isInfoEnabled()) {
s_logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name)); s_logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name));
} }
nets.put(name, new NetworkPrerequisiteTO()); nets.put(name, new OVFNetworkTO());
} }
NetworkPrerequisiteTO thisNet = nets.get(name); OVFNetworkTO thisNet = nets.get(name);
if (e.getParentNode() != null) { if (e.getParentNode() != null) {
fillNicPrerequisites(thisNet,e.getParentNode()); fillNicPrerequisites(thisNet,e.getParentNode());
} }
@ -625,7 +630,7 @@ public class OVFHelper {
* @param nic the object to carry through the system * @param nic the object to carry through the system
* @param parentNode the xml container node for nic data * @param parentNode the xml container node for nic data
*/ */
private void fillNicPrerequisites(NetworkPrerequisiteTO nic, Node parentNode) { private void fillNicPrerequisites(OVFNetworkTO nic, Node parentNode) {
String addressOnParentStr = getChildNodeValue(parentNode, "AddressOnParent"); String addressOnParentStr = getChildNodeValue(parentNode, "AddressOnParent");
String automaticAllocationStr = getChildNodeValue(parentNode, "AutomaticAllocation"); String automaticAllocationStr = getChildNodeValue(parentNode, "AutomaticAllocation");
String description = getChildNodeValue(parentNode, "Description"); String description = getChildNodeValue(parentNode, "Description");
@ -667,9 +672,9 @@ public class OVFHelper {
} }
} }
private Map<String, NetworkPrerequisiteTO> getNetworksFromDocumentTree(Document doc) { private Map<String, OVFNetworkTO> getNetworksFromDocumentTree(Document doc) {
NodeList networkElements = doc.getElementsByTagName("Network"); NodeList networkElements = doc.getElementsByTagName("Network");
Map<String, NetworkPrerequisiteTO> nets = new HashMap<>(); Map<String, OVFNetworkTO> nets = new HashMap<>();
for (int i = 0; i < networkElements.getLength(); i++) { for (int i = 0; i < networkElements.getLength(); i++) {
Element networkElement = (Element)networkElements.item(i); Element networkElement = (Element)networkElements.item(i);
@ -677,7 +682,7 @@ public class OVFHelper {
String description = getChildNodeValue(networkElement, "Description"); String description = getChildNodeValue(networkElement, "Description");
NetworkPrerequisiteTO network = new NetworkPrerequisiteTO(); OVFNetworkTO network = new OVFNetworkTO();
network.setName(networkName); network.setName(networkName);
network.setNetworkDescription(description); network.setNetworkDescription(description);

View File

@ -16,36 +16,37 @@
// under the License. // under the License.
package com.cloud.agent.api.to; package com.cloud.agent.api.to;
import com.cloud.agent.api.LogLevel;
import java.util.HashMap;
import java.util.Map;
public class DeployAsIsInfoTO { public class DeployAsIsInfoTO {
private boolean deployAsIs;
private String templatePath; private String templatePath;
private String deploymentConfiguration; private String destStoragePool;
@LogLevel(LogLevel.Log4jLevel.Off)
private Map<String, String> properties = new HashMap<>();
public DeployAsIsInfoTO() { public DeployAsIsInfoTO() {
} }
public boolean isDeployAsIs() { public DeployAsIsInfoTO(String templatePath, String destStoragePool, Map<String, String> properties) {
return deployAsIs; this.templatePath = templatePath;
} this.destStoragePool = destStoragePool;
this.properties = properties;
public void setDeployAsIs(boolean deployAsIs) {
this.deployAsIs = deployAsIs;
} }
public String getTemplatePath() { public String getTemplatePath() {
return templatePath; return templatePath;
} }
public void setTemplatePath(String templateInSecondaryPath) { public Map<String, String> getProperties() {
this.templatePath = templateInSecondaryPath; return properties;
} }
public String getDeploymentConfiguration() { public String getDestStoragePool() {
return deploymentConfiguration; return destStoragePool;
} }
public void setDeploymentConfiguration(String deploymentConfiguration) {
this.deploymentConfiguration = deploymentConfiguration;
}
} }

View File

@ -20,8 +20,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import com.cloud.agent.api.LogLevel;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachine.Type;
@ -80,8 +78,6 @@ public class VirtualMachineTO {
Map<String, String> guestOsDetails = new HashMap<String, String>(); Map<String, String> guestOsDetails = new HashMap<String, String>();
Map<String, String> extraConfig = new HashMap<>(); Map<String, String> extraConfig = new HashMap<>();
@LogLevel(LogLevel.Log4jLevel.Off)
List<OVFPropertyTO> ovfProperties;
DeployAsIsInfoTO deployAsIsInfo; DeployAsIsInfoTO deployAsIsInfo;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader, public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
@ -376,13 +372,6 @@ public class VirtualMachineTO {
return extraConfig; return extraConfig;
} }
public List<OVFPropertyTO> getOvfProperties() {
return ovfProperties;
}
public void setOvfProperties(List<OVFPropertyTO> ovfProperties) {
this.ovfProperties = ovfProperties;
}
public String getBootType() { public String getBootType() {
return bootType; return bootType;
} }

View File

@ -16,11 +16,11 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
// //
package com.cloud.agent.api.storage; package com.cloud.agent.api.to.deployasis;
import java.util.List; import java.util.List;
public class OVFConfigurationTO { public class OVFConfigurationTO implements TemplateDeployAsIsInformationTO {
private final String id; private final String id;
private final String label; private final String label;

View File

@ -16,16 +16,14 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
// //
package com.cloud.agent.api.storage; package com.cloud.agent.api.to.deployasis;
import com.cloud.agent.api.LogLevel; import com.cloud.agent.api.LogLevel;
import java.io.Serializable;
/** /**
* End-user licence agreement * End-user licence agreement
*/ */
public class OVFEulaSectionTO implements Serializable { public class OVFEulaSectionTO implements TemplateDeployAsIsInformationTO {
private String info; private String info;
@LogLevel(LogLevel.Log4jLevel.Off) @LogLevel(LogLevel.Log4jLevel.Off)
private byte[] compressedLicense; private byte[] compressedLicense;

View File

@ -14,7 +14,7 @@
// KIND, either express or implied. See the License for the // KIND, either express or implied. See the License for the
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
package org.apache.cloudstack.api.net; package com.cloud.agent.api.to.deployasis;
/** /**
* container for the network prerequisites as found in the appliance template * container for the network prerequisites as found in the appliance template
@ -38,7 +38,7 @@ package org.apache.cloudstack.api.net;
* </Item> * </Item>
* {code} * {code}
*/ */
public class NetworkPrerequisiteTO { public class OVFNetworkTO implements TemplateDeployAsIsInformationTO {
String name; String name;
String networkDescription; String networkDescription;

View File

@ -17,7 +17,7 @@
// under the License. // under the License.
// //
package com.cloud.agent.api.storage; package com.cloud.agent.api.to.deployasis;
import com.cloud.agent.api.LogLevel; import com.cloud.agent.api.LogLevel;
@ -30,7 +30,7 @@ import com.cloud.agent.api.LogLevel;
* Choose "Remote HTTP and SSH Client Routes" to route only traffic destined for the management client(s), when they are on remote networks.</Description> * Choose "Remote HTTP and SSH Client Routes" to route only traffic destined for the management client(s), when they are on remote networks.</Description>
* </Property> * </Property>
*/ */
public class OVFPropertyTO { public class OVFPropertyTO implements TemplateDeployAsIsInformationTO {
private String key; private String key;
private String type; private String type;

View File

@ -14,10 +14,10 @@
// KIND, either express or implied. See the License for the // KIND, either express or implied. See the License for the
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
package com.cloud.agent.api.storage; package com.cloud.agent.api.to.deployasis;
// From: https://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData.xsd // From: https://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData.xsd
public class OVFVirtualHardwareItemTO { public class OVFVirtualHardwareItemTO implements TemplateDeployAsIsInformationTO{
//From: https://schemas.dmtf.org/wbem/cim-html/2/CIM_ResourceAllocationSettingData.html //From: https://schemas.dmtf.org/wbem/cim-html/2/CIM_ResourceAllocationSettingData.html
public enum HardwareResourceType { public enum HardwareResourceType {

View File

@ -16,11 +16,11 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
// //
package com.cloud.agent.api.storage; package com.cloud.agent.api.to.deployasis;
import java.util.List; import java.util.List;
public class OVFVirtualHardwareSectionTO { public class OVFVirtualHardwareSectionTO implements TemplateDeployAsIsInformationTO {
public OVFVirtualHardwareSectionTO() { public OVFVirtualHardwareSectionTO() {
} }

View File

@ -0,0 +1,24 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
package com.cloud.agent.api.to.deployasis;
import java.io.Serializable;
public interface TemplateDeployAsIsInformationTO extends Serializable {
}

View File

@ -0,0 +1,27 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis;
public interface DeployAsIsConstants {
String ACS_PROPERTY_PREFIX = "ACS-property-";
String REQUIRED_NETWORK_PREFIX = "ACS-network-";
String OVF_HARDWARE_CONFIGURATION_PREFIX = "ACS-configuration-";
String OVF_HARDWARE_ITEM_PREFIX = "ACS-hardware-item-";
String OVF_EULA_SECTION_PREFIX = "ACS-eula-";
}

View File

@ -21,13 +21,6 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface ImageStore extends Identity, InternalIdentity { public interface ImageStore extends Identity, InternalIdentity {
String ACS_PROPERTY_PREFIX = "ACS-property-";
String REQUIRED_NETWORK_PREFIX = "ACS-network-";
String DISK_DEFINITION_PREFIX = "ACS-disk-";
String OVF_HARDWARE_CONFIGURATION_PREFIX = "ACS-configuration-";
String OVF_HARDWARE_ITEM_PREFIX = "ACS-hardware-item-";
String OVF_EULA_SECTION_PREFIX = "ACS-eula-";
/** /**
* @return name of the object store. * @return name of the object store.
*/ */

View File

@ -826,6 +826,7 @@ public class ApiConstants {
public static final String BOOT_MODE = "bootmode"; public static final String BOOT_MODE = "bootmode";
public static final String BOOT_INTO_SETUP = "bootintosetup"; public static final String BOOT_INTO_SETUP = "bootintosetup";
public static final String DEPLOY_AS_IS = "deployasis"; public static final String DEPLOY_AS_IS = "deployasis";
public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails";
public static final String CROSS_ZONES = "crossZones"; public static final String CROSS_ZONES = "crossZones";
public static final String TEMPLATETYPE = "templatetype"; public static final String TEMPLATETYPE = "templatetype";
public static final String SOURCETEMPLATEID = "sourcetemplateid"; public static final String SOURCETEMPLATEID = "sourcetemplateid";

View File

@ -199,6 +199,10 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
@Param(description = "VMware only: true if template is deployed without orchestrating disks and networks but \"as-is\" defined in the template.") @Param(description = "VMware only: true if template is deployed without orchestrating disks and networks but \"as-is\" defined in the template.")
private Boolean deployAsIs; private Boolean deployAsIs;
@SerializedName(ApiConstants.DEPLOY_AS_IS_DETAILS)
@Param(description = "VMware only: additional key/value details tied with deploy-as-is template")
private Map<String, String> deployAsIsDetails;
@SerializedName("parenttemplateid") @SerializedName("parenttemplateid")
@Param(description = "if Datadisk template, then id of the root disk template this template belongs to") @Param(description = "if Datadisk template, then id of the root disk template this template belongs to")
@Deprecated(since = "4.15") @Deprecated(since = "4.15")
@ -429,4 +433,19 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
public void setRequiresHvm(Boolean requiresHvm) { public void setRequiresHvm(Boolean requiresHvm) {
this.requiresHvm = requiresHvm; this.requiresHvm = requiresHvm;
} }
public Map<String, String> getDeployAsIsDetails() {
return this.deployAsIsDetails;
}
public void setDeployAsIsDetails(Map<String, String> details) {
this.deployAsIsDetails = details;
}
public void addDeployAsIsDetail(String key, String value) {
if (this.deployAsIsDetails == null) {
setDeployAsIsDetails(new HashMap<>());
}
this.deployAsIsDetails.put(key,value);
}
} }

View File

@ -16,6 +16,10 @@
// under the License. // under the License.
package com.cloud.agent.api.storage; package com.cloud.agent.api.storage;
import com.cloud.agent.api.to.deployasis.OVFConfigurationTO;
import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareItemTO;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;

View File

@ -26,9 +26,12 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.agent.api.LogLevel; import com.cloud.agent.api.LogLevel;
import com.cloud.agent.api.to.DatadiskTO; import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
public class DownloadAnswer extends Answer { public class DownloadAnswer extends Answer {
private String jobId; private String jobId;
@ -44,7 +47,7 @@ public class DownloadAnswer extends Answer {
@LogLevel(LogLevel.Log4jLevel.Off) @LogLevel(LogLevel.Log4jLevel.Off)
private List<OVFPropertyTO> ovfProperties; private List<OVFPropertyTO> ovfProperties;
@LogLevel(LogLevel.Log4jLevel.Off) @LogLevel(LogLevel.Log4jLevel.Off)
private List<NetworkPrerequisiteTO> networkRequirements; private List<OVFNetworkTO> networkRequirements;
@LogLevel(LogLevel.Log4jLevel.Off) @LogLevel(LogLevel.Log4jLevel.Off)
private List<DatadiskTO> disks; private List<DatadiskTO> disks;
@LogLevel(LogLevel.Log4jLevel.Off) @LogLevel(LogLevel.Log4jLevel.Off)
@ -169,11 +172,11 @@ public class DownloadAnswer extends Answer {
this.ovfProperties = ovfProperties; this.ovfProperties = ovfProperties;
} }
public List<NetworkPrerequisiteTO> getNetworkRequirements() { public List<OVFNetworkTO> getNetworkRequirements() {
return networkRequirements; return networkRequirements;
} }
public void setNetworkRequirements(List<NetworkPrerequisiteTO> networkRequirements) { public void setNetworkRequirements(List<OVFNetworkTO> networkRequirements) {
this.networkRequirements = networkRequirements; this.networkRequirements = networkRequirements;
} }

View File

@ -28,12 +28,12 @@ import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import com.cloud.agent.api.storage.OVFConfigurationTO; import com.cloud.agent.api.to.deployasis.OVFConfigurationTO;
import com.cloud.agent.api.storage.OVFEulaSectionTO; import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareItemTO; import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareItemTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareSectionTO; import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -115,7 +115,7 @@ public class OVAProcessor extends AdapterBase implements Processor {
info.disks = disks; info.disks = disks;
} }
List<NetworkPrerequisiteTO> nets = ovfHelper.getNetPrerequisitesFromDocument(doc); List<OVFNetworkTO> nets = ovfHelper.getNetPrerequisitesFromDocument(doc);
if (CollectionUtils.isNotEmpty(nets)) { if (CollectionUtils.isNotEmpty(nets)) {
LOGGER.info("Found " + nets.size() + " prerequisite networks"); LOGGER.info("Found " + nets.size() + " prerequisite networks");
info.networks = nets; info.networks = nets;

View File

@ -23,14 +23,14 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import com.cloud.agent.api.storage.OVFEulaSectionTO; import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareSectionTO; import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import com.cloud.agent.api.to.DatadiskTO; import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
import com.cloud.utils.component.Adapter; import com.cloud.utils.component.Adapter;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
/** /**
* Generic interface to process different types of image formats * Generic interface to process different types of image formats
@ -59,7 +59,7 @@ public interface Processor extends Adapter {
public String filename; public String filename;
public boolean isCorrupted; public boolean isCorrupted;
public List<OVFPropertyTO> ovfProperties; public List<OVFPropertyTO> ovfProperties;
public List<NetworkPrerequisiteTO> networks; public List<OVFNetworkTO> networks;
public List<DatadiskTO> disks; public List<DatadiskTO> disks;
public OVFVirtualHardwareSectionTO hardwareSection; public OVFVirtualHardwareSectionTO hardwareSection;
public List<OVFEulaSectionTO> eulaSections; public List<OVFEulaSectionTO> eulaSections;

View File

@ -17,10 +17,11 @@
package com.cloud.agent.api.storage; package com.cloud.agent.api.storage;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -45,8 +46,8 @@ public class DownloadAnswerTest {
{ {
List<OVFPropertyTO> properties = new ArrayList<>(); List<OVFPropertyTO> properties = new ArrayList<>();
properties.add(new OVFPropertyTO()); properties.add(new OVFPropertyTO());
List<NetworkPrerequisiteTO> networks = new ArrayList<>(); List<OVFNetworkTO> networks = new ArrayList<>();
networks.add(new NetworkPrerequisiteTO()); networks.add(new OVFNetworkTO());
answer.setOvfProperties(properties); answer.setOvfProperties(properties);
answer.setNetworkRequirements(networks); answer.setNetworkRequirements(networks);

View File

@ -1472,8 +1472,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (disk.getType() != Volume.Type.ISO) { if (disk.getType() != Volume.Type.ISO) {
final VolumeObjectTO vol = (VolumeObjectTO)disk.getData(); final VolumeObjectTO vol = (VolumeObjectTO)disk.getData();
final VolumeVO volume = _volsDao.findById(vol.getId()); final VolumeVO volume = _volsDao.findById(vol.getId());
if (vmSpec.getDeployAsIsInfo() != null && vmSpec.getDeployAsIsInfo().isDeployAsIs() if (vmSpec.getDeployAsIsInfo() != null && StringUtils.isNotBlank(vol.getPath())) {
&& StringUtils.isNotBlank(vol.getPath())) {
volume.setPath(vol.getPath()); volume.setPath(vol.getPath());
_volsDao.update(volume.getId(), volume); _volsDao.update(volume.getId(), volume);
} }

View File

@ -40,9 +40,10 @@ import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO; import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao; import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao;
@ -181,7 +182,6 @@ import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao; import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.ResourceLimitService; import com.cloud.user.ResourceLimitService;
import com.cloud.user.User; import com.cloud.user.User;
@ -304,7 +304,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
@Inject @Inject
UserVmManager _userVmMgr; UserVmManager _userVmMgr;
@Inject @Inject
VMTemplateDetailsDao templateDetailsDao; TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
List<NetworkGuru> networkGurus; List<NetworkGuru> networkGurus;
@ -884,7 +884,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
} }
} }
List<NetworkPrerequisiteTO> netprereqs = templateDetailsDao.listNetworkRequirementsByTemplateId(vm.getTemplate().getId()); List<OVFNetworkTO> netprereqs = templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(vm.getTemplate().getId());
if (size < netprereqs.size()) { if (size < netprereqs.size()) {
size = netprereqs.size(); size = netprereqs.size();
} }

View File

@ -0,0 +1,94 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail;
@Entity
@Table(name = "template_deploy_as_is_details")
public class TemplateDeployAsIsDetailVO implements ResourceDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "template_id")
private long templateId;
@Column(name = "name")
private String name;
@Lob
@Column(name = "value", length = 65535)
private String value;
public TemplateDeployAsIsDetailVO() {
}
public TemplateDeployAsIsDetailVO(long templateId, String name, String value) {
this.templateId = templateId;
this.name = name;
this.value = value;
}
@Override
public long getId() {
return id;
}
public long getResourceId() {
return templateId;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public boolean isDisplay() {
return true;
}
public void setId(long id) {
this.id = id;
}
public void setTemplateId(long resourceId) {
this.templateId = resourceId;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,94 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail;
@Entity
@Table(name = "template_deploy_as_is_details")
public class TemplateDeployAsIsDetailVO implements ResourceDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "template_id")
private long resourceId;
@Column(name = "name")
private String name;
@Lob
@Column(name = "value", length = 65535)
private String value;
public TemplateDeployAsIsDetailVO() {
}
public TemplateDeployAsIsDetailVO(long templateId, String name, String value) {
this.resourceId = templateId;
this.name = name;
this.value = value;
}
@Override
public long getId() {
return id;
}
public long getResourceId() {
return resourceId;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public boolean isDisplay() {
return true;
}
public void setId(long id) {
this.id = id;
}
public void setResourceId(long resourceId) {
this.resourceId = resourceId;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,94 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail;
@Entity
@Table(name = "user_vm_deploy_as_is_details")
public class UserVmDeployAsIsDetailVO implements ResourceDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "vm_id")
private long vmId;
@Column(name = "name")
private String name;
@Lob
@Column(name = "value", length = 65535)
private String value;
public UserVmDeployAsIsDetailVO() {
}
public UserVmDeployAsIsDetailVO(long vmId, String name, String value) {
this.vmId = vmId;
this.name = name;
this.value = value;
}
@Override
public long getId() {
return id;
}
public long getResourceId() {
return vmId;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public boolean isDisplay() {
return true;
}
public void setId(long id) {
this.id = id;
}
public void setVmId(long resourceId) {
this.vmId = resourceId;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,94 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail;
@Entity
@Table(name = "user_vm_deploy_as_is_details")
public class UserVmDeployAsIsDetailVO implements ResourceDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "vm_id")
private long resourceId;
@Column(name = "name")
private String name;
@Lob
@Column(name = "value", length = 65535)
private String value;
public UserVmDeployAsIsDetailVO() {
}
public UserVmDeployAsIsDetailVO(long vmId, String name, String value) {
this.resourceId = vmId;
this.name = name;
this.value = value;
}
@Override
public long getId() {
return id;
}
public long getResourceId() {
return resourceId;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public boolean isDisplay() {
return true;
}
public void setId(long id) {
this.id = id;
}
public void setResourceId(long resourceId) {
this.resourceId = resourceId;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis.dao;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.utils.db.GenericDao;
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
import java.util.List;
public interface TemplateDeployAsIsDetailsDao extends GenericDao<TemplateDeployAsIsDetailVO, Long>, ResourceDetailsDao<TemplateDeployAsIsDetailVO> {
OVFPropertyTO findPropertyByTemplateAndKey(long templateId, String key);
List<TemplateDeployAsIsDetailVO> listDetailsByTemplateIdMatchingPrefix(long templateId, String prefix);
List<OVFNetworkTO> listNetworkRequirementsByTemplateId(long templateId);
}

View File

@ -0,0 +1,83 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis.dao;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.utils.db.SearchCriteria;
import com.google.gson.Gson;
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@Component
public class TemplateDeployAsIsDetailsDaoImpl extends ResourceDetailsDaoBase<TemplateDeployAsIsDetailVO> implements TemplateDeployAsIsDetailsDao {
private Gson gson = new Gson();
public TemplateDeployAsIsDetailsDaoImpl() {
}
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new TemplateDeployAsIsDetailVO(resourceId, key, value));
}
@Override
public OVFPropertyTO findPropertyByTemplateAndKey(long templateId, String key) {
SearchCriteria<TemplateDeployAsIsDetailVO> sc = createSearchCriteria();
sc.addAnd("templateId", SearchCriteria.Op.EQ, templateId);
sc.addAnd("name", SearchCriteria.Op.EQ, key.startsWith(DeployAsIsConstants.ACS_PROPERTY_PREFIX) ? key : DeployAsIsConstants.ACS_PROPERTY_PREFIX + key);
OVFPropertyTO property = null;
TemplateDeployAsIsDetailVO detail = findOneBy(sc);
if (detail != null) {
property = gson.fromJson(detail.getValue(), OVFPropertyTO.class);
}
return property;
}
@Override
public List<TemplateDeployAsIsDetailVO> listDetailsByTemplateIdMatchingPrefix(long templateId, String prefix) {
SearchCriteria<TemplateDeployAsIsDetailVO> ssc = createSearchCriteria();
ssc.addAnd("templateId", SearchCriteria.Op.EQ, templateId);
ssc.addAnd("name", SearchCriteria.Op.LIKE, prefix + "%");
return search(ssc, null);
}
@Override
public List<OVFNetworkTO> listNetworkRequirementsByTemplateId(long templateId) {
List<TemplateDeployAsIsDetailVO> networkDetails = listDetailsByTemplateIdMatchingPrefix(templateId, DeployAsIsConstants.REQUIRED_NETWORK_PREFIX);
List<OVFNetworkTO> networkPrereqs = new ArrayList<>();
for (TemplateDeployAsIsDetailVO property : networkDetails) {
OVFNetworkTO ovfPropertyTO = gson.fromJson(property.getValue(), OVFNetworkTO.class);
networkPrereqs.add(ovfPropertyTO);
}
networkPrereqs.sort(new Comparator<OVFNetworkTO>() {
@Override
public int compare(OVFNetworkTO o1, OVFNetworkTO o2) {
return o1.getInstanceID() - o2.getInstanceID();
}
});
return networkPrereqs;
}
}

View File

@ -0,0 +1,83 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis.dao;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.utils.db.SearchCriteria;
import com.google.gson.Gson;
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@Component
public class TemplateDeployAsIsDetailsDaoImpl extends ResourceDetailsDaoBase<TemplateDeployAsIsDetailVO> implements TemplateDeployAsIsDetailsDao {
private Gson gson = new Gson();
public TemplateDeployAsIsDetailsDaoImpl() {
}
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new TemplateDeployAsIsDetailVO(resourceId, key, value));
}
@Override
public OVFPropertyTO findPropertyByTemplateAndKey(long templateId, String key) {
SearchCriteria<TemplateDeployAsIsDetailVO> sc = createSearchCriteria();
sc.addAnd("resourceId", SearchCriteria.Op.EQ, templateId);
sc.addAnd("name", SearchCriteria.Op.EQ, key.startsWith(DeployAsIsConstants.ACS_PROPERTY_PREFIX) ? key : DeployAsIsConstants.ACS_PROPERTY_PREFIX + key);
OVFPropertyTO property = null;
TemplateDeployAsIsDetailVO detail = findOneBy(sc);
if (detail != null) {
property = gson.fromJson(detail.getValue(), OVFPropertyTO.class);
}
return property;
}
@Override
public List<TemplateDeployAsIsDetailVO> listDetailsByTemplateIdMatchingPrefix(long templateId, String prefix) {
SearchCriteria<TemplateDeployAsIsDetailVO> ssc = createSearchCriteria();
ssc.addAnd("resouceId", SearchCriteria.Op.EQ, templateId);
ssc.addAnd("name", SearchCriteria.Op.LIKE, prefix + "%");
return search(ssc, null);
}
@Override
public List<OVFNetworkTO> listNetworkRequirementsByTemplateId(long templateId) {
List<TemplateDeployAsIsDetailVO> networkDetails = listDetailsByTemplateIdMatchingPrefix(templateId, DeployAsIsConstants.REQUIRED_NETWORK_PREFIX);
List<OVFNetworkTO> networkPrereqs = new ArrayList<>();
for (TemplateDeployAsIsDetailVO property : networkDetails) {
OVFNetworkTO ovfPropertyTO = gson.fromJson(property.getValue(), OVFNetworkTO.class);
networkPrereqs.add(ovfPropertyTO);
}
networkPrereqs.sort(new Comparator<OVFNetworkTO>() {
@Override
public int compare(OVFNetworkTO o1, OVFNetworkTO o2) {
return o1.getInstanceID() - o2.getInstanceID();
}
});
return networkPrereqs;
}
}

View File

@ -0,0 +1,24 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis.dao;
import com.cloud.deployasis.UserVmDeployAsIsDetailVO;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
public interface UserVmDeployAsIsDetailsDao extends GenericDao<UserVmDeployAsIsDetailVO, Long>, ResourceDetailsDao<UserVmDeployAsIsDetailVO> {
}

View File

@ -0,0 +1,30 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deployasis.dao;
import com.cloud.deployasis.UserVmDeployAsIsDetailVO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
import org.springframework.stereotype.Component;
@Component
public class UserVmDeployAsIsDetailsDaoImpl extends ResourceDetailsDaoBase<UserVmDeployAsIsDetailVO> implements UserVmDeployAsIsDetailsDao {
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new UserVmDeployAsIsDetailVO(resourceId, key, value));
}
}

View File

@ -21,7 +21,6 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table; import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail; import org.apache.cloudstack.api.ResourceDetail;
@ -40,8 +39,7 @@ public class VMTemplateDetailVO implements ResourceDetail {
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@Lob @Column(name = "value", length = 1024)
@Column(name = "value", length = 65535)
private String value; private String value;
@Column(name = "display") @Column(name = "display")

View File

@ -16,25 +16,11 @@
// under the License. // under the License.
package com.cloud.storage.dao; package com.cloud.storage.dao;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.agent.api.to.DatadiskTO;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
import com.cloud.storage.VMTemplateDetailVO; import com.cloud.storage.VMTemplateDetailVO;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import java.util.List;
public interface VMTemplateDetailsDao extends GenericDao<VMTemplateDetailVO, Long>, ResourceDetailsDao<VMTemplateDetailVO> { public interface VMTemplateDetailsDao extends GenericDao<VMTemplateDetailVO, Long>, ResourceDetailsDao<VMTemplateDetailVO> {
boolean existsOption(long templateId, String key);
OVFPropertyTO findPropertyByTemplateAndKey(long templateId, String key);
void saveOptions(List<OVFPropertyTO> opts);
List<OVFPropertyTO> listPropertiesByTemplateId(long templateId);
List<NetworkPrerequisiteTO> listNetworkRequirementsByTemplateId(long templateId);
List<DatadiskTO> listDisksByTemplateId(long templateId);
List<VMTemplateDetailVO> listDetailsByTemplateIdMatchingPrefix(long templateId, String prefix);
String getTemplateEulaSectionsUrl(long templateId);
} }

View File

@ -17,137 +17,17 @@
package com.cloud.storage.dao; package com.cloud.storage.dao;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.agent.api.storage.OVFPropertyTO; import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.storage.ImageStore;
import com.cloud.storage.VMTemplateDetailVO; import com.cloud.storage.VMTemplateDetailVO;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.google.gson.Gson;
@Component @Component
public class VMTemplateDetailsDaoImpl extends ResourceDetailsDaoBase<VMTemplateDetailVO> implements VMTemplateDetailsDao { public class VMTemplateDetailsDaoImpl extends ResourceDetailsDaoBase<VMTemplateDetailVO> implements VMTemplateDetailsDao {
private final static Logger LOGGER = Logger.getLogger(VMTemplateDetailsDaoImpl.class);
Gson gson = new Gson();
SearchBuilder<VMTemplateDetailVO> OptionsSearchBuilder;
public VMTemplateDetailsDaoImpl() {
super();
OptionsSearchBuilder = createSearchBuilder();
OptionsSearchBuilder.and("resourceId", OptionsSearchBuilder.entity().getResourceId(), SearchCriteria.Op.EQ);
OptionsSearchBuilder.and("name", OptionsSearchBuilder.entity().getName(), SearchCriteria.Op.EQ);
OptionsSearchBuilder.done();
}
@Override @Override
public void addDetail(long resourceId, String key, String value, boolean display) { public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new VMTemplateDetailVO(resourceId, key, value, display)); super.addDetail(new VMTemplateDetailVO(resourceId, key, value, display));
} }
@Override
public boolean existsOption(long templateId, String key) {
return findPropertyByTemplateAndKey(templateId, key) != null;
}
@Override
public OVFPropertyTO findPropertyByTemplateAndKey(long templateId, String key) {
SearchCriteria<VMTemplateDetailVO> sc = OptionsSearchBuilder.create();
sc.setParameters("resourceId", templateId);
sc.setParameters("name", key.startsWith(ImageStore.ACS_PROPERTY_PREFIX) ? key : ImageStore.ACS_PROPERTY_PREFIX + key);
OVFPropertyTO property = null;
VMTemplateDetailVO detail = findOneBy(sc);
if (detail != null) {
property = gson.fromJson(detail.getValue(), OVFPropertyTO.class);
}
return property;
}
@Override
public void saveOptions(List<OVFPropertyTO> opts) {
if (CollectionUtils.isEmpty(opts)) {
return;
}
TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
for (OVFPropertyTO opt : opts) {
String json = gson.toJson(opt);
VMTemplateDetailVO templateDetailVO = new VMTemplateDetailVO(opt.getTemplateId(), ImageStore.ACS_PROPERTY_PREFIX + opt.getKey(), json, opt.isUserConfigurable());
persist(templateDetailVO);
}
txn.commit();
}
@Override
public List<OVFPropertyTO> listPropertiesByTemplateId(long templateId) {
List<VMTemplateDetailVO> ovfProperties = listDetailsByTemplateIdMatchingPrefix(templateId, ImageStore.ACS_PROPERTY_PREFIX);
List<OVFPropertyTO> properties = new ArrayList<>();
for (VMTemplateDetailVO property : ovfProperties) {
OVFPropertyTO ovfPropertyTO = gson.fromJson(property.getValue(), OVFPropertyTO.class);
properties.add(ovfPropertyTO);
}
return properties;
}
@Override
public List<NetworkPrerequisiteTO> listNetworkRequirementsByTemplateId(long templateId) {
List<VMTemplateDetailVO> networkDetails = listDetailsByTemplateIdMatchingPrefix(templateId, ImageStore.REQUIRED_NETWORK_PREFIX);
List<NetworkPrerequisiteTO> networkPrereqs = new ArrayList<>();
for (VMTemplateDetailVO property : networkDetails) {
NetworkPrerequisiteTO ovfPropertyTO = gson.fromJson(property.getValue(), NetworkPrerequisiteTO.class);
networkPrereqs.add(ovfPropertyTO);
}
networkPrereqs.sort(new Comparator<NetworkPrerequisiteTO>() {
@Override
public int compare(NetworkPrerequisiteTO o1, NetworkPrerequisiteTO o2) {
return o1.getInstanceID() - o2.getInstanceID();
}
});
return networkPrereqs;
}
@Override
public List<DatadiskTO> listDisksByTemplateId(long templateId) {
List<VMTemplateDetailVO> diskDefinitions = listDetailsByTemplateIdMatchingPrefix(templateId, ImageStore.DISK_DEFINITION_PREFIX);
List<DatadiskTO> disks = new ArrayList<>();
for (VMTemplateDetailVO detail : diskDefinitions) {
DatadiskTO datadiskTO = gson.fromJson(detail.getValue(), DatadiskTO.class);
disks.add(datadiskTO);
}
return disks;
}
@Override
public List<VMTemplateDetailVO> listDetailsByTemplateIdMatchingPrefix(long templateId, String prefix) {
SearchCriteria<VMTemplateDetailVO> ssc = createSearchCriteria();
ssc.addAnd("resourceId", SearchCriteria.Op.EQ, templateId);
ssc.addAnd("name", SearchCriteria.Op.LIKE, prefix + "%");
return search(ssc, null);
}
@Override
public String getTemplateEulaSectionsUrl(long templateId) {
List<VMTemplateDetailVO> details = findDetails(templateId, ImageStore.OVF_EULA_SECTION_PREFIX);
if (CollectionUtils.isEmpty(details)) {
return null;
}
if (details.size() > 1) {
LOGGER.error("Multiple details for EULA sections for template " + templateId + " returning one");
}
return details.get(0).getValue();
}
} }

View File

@ -30,7 +30,6 @@ import javax.annotation.PostConstruct;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.storage.ImageStore;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -383,25 +382,13 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
List<UserVmDetailVO> details = new ArrayList<UserVmDetailVO>(); List<UserVmDetailVO> details = new ArrayList<UserVmDetailVO>();
for (Map.Entry<String, String> entry : detailsStr.entrySet()) { for (Map.Entry<String, String> entry : detailsStr.entrySet()) {
boolean display = visibilityMap.getOrDefault(entry.getKey(), true) && displayOVFDetails(entry.getKey()); boolean display = visibilityMap.getOrDefault(entry.getKey(), true);
details.add(new UserVmDetailVO(vm.getId(), entry.getKey(), entry.getValue(), display)); details.add(new UserVmDetailVO(vm.getId(), entry.getKey(), entry.getValue(), display));
} }
_detailsDao.saveDetails(details); _detailsDao.saveDetails(details);
} }
/*
Do not display VM properties parsed from OVF, handled internally
*/
private boolean displayOVFDetails(String key) {
if (key.startsWith(ImageStore.ACS_PROPERTY_PREFIX) || key.startsWith(ImageStore.OVF_HARDWARE_ITEM_PREFIX) ||
key.startsWith(ImageStore.OVF_HARDWARE_CONFIGURATION_PREFIX) || key.startsWith(ImageStore.DISK_DEFINITION_PREFIX) ||
key.startsWith(ImageStore.REQUIRED_NETWORK_PREFIX) || key.startsWith(ImageStore.OVF_EULA_SECTION_PREFIX)) {
return false;
}
return true;
}
@Override @Override
public List<Long> listPodIdsHavingVmsforAccount(long zoneId, long accountId) { public List<Long> listPodIdsHavingVmsforAccount(long zoneId, long accountId) {
TransactionLegacy txn = TransactionLegacy.currentTxn(); TransactionLegacy txn = TransactionLegacy.currentTxn();

View File

@ -295,4 +295,6 @@
<bean id="directDownloadCertificateHostMapDaoImpl" class="org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMapDaoImpl" /> <bean id="directDownloadCertificateHostMapDaoImpl" class="org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMapDaoImpl" />
<bean id="routerHealthCheckResultsDaoImpl" class="com.cloud.network.dao.RouterHealthCheckResultDaoImpl" /> <bean id="routerHealthCheckResultsDaoImpl" class="com.cloud.network.dao.RouterHealthCheckResultDaoImpl" />
<bean id="VsphereStoragePolicyDaoImpl" class="com.cloud.dc.dao.VsphereStoragePolicyDaoImpl" /> <bean id="VsphereStoragePolicyDaoImpl" class="com.cloud.dc.dao.VsphereStoragePolicyDaoImpl" />
<bean id="TemplateDeployAsIsDetailsDaoImpl" class="com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDaoImpl" />
<bean id="UserVmDeployAsIsDetailsDaoImpl" class="com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDaoImpl" />
</beans> </beans>

View File

@ -473,6 +473,92 @@ ADD CONSTRAINT `fk_template_spool_ref__template_id`
ON DELETE NO ACTION ON DELETE NO ACTION
ON UPDATE NO ACTION; ON UPDATE NO ACTION;
CREATE TABLE IF NOT EXISTS `cloud`.`vsphere_storage_policy` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) UNIQUE,
`zone_id` bigint(20) unsigned NOT NULL COMMENT 'id of the zone',
`policy_id` varchar(255) NOT NULL COMMENT 'the identifier of the Storage Policy in vSphere DataCenter',
`name` varchar(255) NOT NULL COMMENT 'name of the storage policy',
`description` text COMMENT 'description of the storage policy',
`update_time` datetime COMMENT 'last updated when policy imported',
`removed` datetime COMMENT 'date removed',
PRIMARY KEY (`id`),
KEY `fk_vsphere_storage_policy__zone_id` (`zone_id`),
UNIQUE KEY (`zone_id`, `policy_id`),
CONSTRAINT `fk_vsphere_storage_policy__zone_id` FOREIGN KEY (`zone_id`) REFERENCES `data_center` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`storage_pool` ADD COLUMN `parent` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'ID of the Datastore cluster (storage pool) if this is a child in that Datastore cluster';
-- Added parent column to support datastore clusters in vmware vsphere
DROP VIEW IF EXISTS `cloud`.`storage_pool_view`;
CREATE VIEW `cloud`.`storage_pool_view` AS
SELECT
`storage_pool`.`id` AS `id`,
`storage_pool`.`uuid` AS `uuid`,
`storage_pool`.`name` AS `name`,
`storage_pool`.`status` AS `status`,
`storage_pool`.`path` AS `path`,
`storage_pool`.`pool_type` AS `pool_type`,
`storage_pool`.`host_address` AS `host_address`,
`storage_pool`.`created` AS `created`,
`storage_pool`.`removed` AS `removed`,
`storage_pool`.`capacity_bytes` AS `capacity_bytes`,
`storage_pool`.`capacity_iops` AS `capacity_iops`,
`storage_pool`.`scope` AS `scope`,
`storage_pool`.`hypervisor` AS `hypervisor`,
`storage_pool`.`storage_provider_name` AS `storage_provider_name`,
`storage_pool`.`parent` AS `parent`,
`cluster`.`id` AS `cluster_id`,
`cluster`.`uuid` AS `cluster_uuid`,
`cluster`.`name` AS `cluster_name`,
`cluster`.`cluster_type` AS `cluster_type`,
`data_center`.`id` AS `data_center_id`,
`data_center`.`uuid` AS `data_center_uuid`,
`data_center`.`name` AS `data_center_name`,
`data_center`.`networktype` AS `data_center_type`,
`host_pod_ref`.`id` AS `pod_id`,
`host_pod_ref`.`uuid` AS `pod_uuid`,
`host_pod_ref`.`name` AS `pod_name`,
`storage_pool_tags`.`tag` AS `tag`,
`op_host_capacity`.`used_capacity` AS `disk_used_capacity`,
`op_host_capacity`.`reserved_capacity` AS `disk_reserved_capacity`,
`async_job`.`id` AS `job_id`,
`async_job`.`uuid` AS `job_uuid`,
`async_job`.`job_status` AS `job_status`,
`async_job`.`account_id` AS `job_account_id`
FROM
((((((`storage_pool`
LEFT JOIN `cluster` ON ((`storage_pool`.`cluster_id` = `cluster`.`id`)))
LEFT JOIN `data_center` ON ((`storage_pool`.`data_center_id` = `data_center`.`id`)))
LEFT JOIN `host_pod_ref` ON ((`storage_pool`.`pod_id` = `host_pod_ref`.`id`)))
LEFT JOIN `storage_pool_tags` ON (((`storage_pool_tags`.`pool_id` = `storage_pool`.`id`))))
LEFT JOIN `op_host_capacity` ON (((`storage_pool`.`id` = `op_host_capacity`.`host_id`)
AND (`op_host_capacity`.`capacity_type` IN (3 , 9)))))
LEFT JOIN `async_job` ON (((`async_job`.`instance_id` = `storage_pool`.`id`)
AND (`async_job`.`instance_type` = 'StoragePool')
AND (`async_job`.`job_status` = 0))));
CREATE TABLE `cloud`.`template_deploy_as_is_details` (
`id` bigint unsigned NOT NULL auto_increment,
`template_id` bigint unsigned NOT NULL COMMENT 'template id',
`name` varchar(255) NOT NULL,
`value` TEXT,
PRIMARY KEY (`id`),
CONSTRAINT `fk_template_deploy_as_is_details__template_id` FOREIGN KEY `fk_template_deploy_as_is_details__template_id`(`template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`user_vm_deploy_as_is_details` (
`id` bigint unsigned NOT NULL auto_increment,
`vm_id` bigint unsigned NOT NULL COMMENT 'virtual machine id',
`name` varchar(255) NOT NULL,
`value` TEXT,
PRIMARY KEY (`id`),
CONSTRAINT `fk_user_vm_deploy_as_is_details__vm_id` FOREIGN KEY `fk_user_vm_deploy_as_is_details__vm_id`(`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`image_store` ADD COLUMN `readonly` boolean DEFAULT false COMMENT 'defines status of image store'; ALTER TABLE `cloud`.`image_store` ADD COLUMN `readonly` boolean DEFAULT false COMMENT 'defines status of image store';
ALTER VIEW `cloud`.`image_store_view` AS ALTER VIEW `cloud`.`image_store_view` AS

View File

@ -18,7 +18,6 @@
*/ */
package org.apache.cloudstack.storage.image; package org.apache.cloudstack.storage.image;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -33,19 +32,8 @@ import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.agent.api.storage.OVFConfigurationTO;
import com.cloud.agent.api.storage.OVFEulaSectionTO;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareItemTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareSectionTO;
import com.cloud.storage.ImageStore;
import com.cloud.storage.Upload; import com.cloud.storage.Upload;
import com.cloud.storage.VMTemplateDetailVO; import org.apache.cloudstack.storage.image.deployasis.DeployAsIsHelper;
import com.cloud.utils.compression.CompressionUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
@ -89,7 +77,6 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO; import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor; import com.cloud.storage.download.DownloadMonitor;
@ -123,14 +110,14 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
@Inject @Inject
AlertManager _alertMgr; AlertManager _alertMgr;
@Inject @Inject
VMTemplateDetailsDao templateDetailsDao;
@Inject
DefaultEndPointSelector _defaultEpSelector; DefaultEndPointSelector _defaultEpSelector;
@Inject @Inject
AccountDao _accountDao; AccountDao _accountDao;
@Inject @Inject
ResourceLimitService _resourceLimitMgr; ResourceLimitService _resourceLimitMgr;
@Inject @Inject
DeployAsIsHelper deployAsIsHelper;
@Inject
HostDao hostDao; HostDao hostDao;
@Inject @Inject
CommandExecLogDao _cmdExecLogDao; CommandExecLogDao _cmdExecLogDao;
@ -143,14 +130,6 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
protected String _proxy = null; protected String _proxy = null;
private static Gson gson;
static {
GsonBuilder builder = new GsonBuilder();
builder.disableHtmlEscaping();
gson = builder.create();
}
protected Proxy getHttpProxy() { protected Proxy getHttpProxy() {
if (_proxy == null) { if (_proxy == null) {
return null; return null;
@ -211,91 +190,6 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
} }
} }
/**
* Persist OVF properties as template details for template with id = templateId
*/
private void persistOVFProperties(List<OVFPropertyTO> ovfProperties, long templateId) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving properties for template %d as details", templateId));
}
for (OVFPropertyTO property : ovfProperties) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving property %s for template %d as detail", property.getKey(), templateId));
}
persistOvfPropertyAsSetOfTemplateDetails(templateId, property);
}
}
private void persistOvfPropertyAsSetOfTemplateDetails(long templateId, OVFPropertyTO property) {
String key = property.getKey();
String propKey = ImageStore.ACS_PROPERTY_PREFIX + key;
try {
String propValue = gson.toJson(property);
savePropertyAttribute(templateId, propKey, propValue);
} catch (RuntimeException re) {
LOGGER.error("gson marshalling of property object fails: " + propKey,re);
}
}
private void persistNetworkRequirements(List<NetworkPrerequisiteTO> networkRequirements, long templateId) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving network requirements for template %d as details", templateId));
}
for (NetworkPrerequisiteTO network : networkRequirements) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving property %s for template %d as detail", network.getName(), templateId));
}
persistRequiredNetworkAsASingleTemplateDetail(templateId, network);
}
}
private void persistDiskDefinitions(List<DatadiskTO> disks, long templateId) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving disk definitionsn for template %d as details", templateId));
}
for (DatadiskTO disk : disks) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving property %s for template %d as detail", disk.getDiskId(), templateId));
}
persistDiskDefinitionAsASingleTemplateDetail(templateId, disk);
}
}
private void persistRequiredNetworkAsASingleTemplateDetail(long templateId, NetworkPrerequisiteTO network) {
String key = network.getName();
String propKey = ImageStore.REQUIRED_NETWORK_PREFIX + key;
try {
String propValue = gson.toJson(network);
savePropertyAttribute(templateId, propKey, propValue);
} catch (RuntimeException re) {
LOGGER.warn("gson marshalling of network object fails: " + propKey,re);
}
}
private void persistDiskDefinitionAsASingleTemplateDetail(long templateId, DatadiskTO disk) {
String key = disk.getDiskId();
String propKey = ImageStore.DISK_DEFINITION_PREFIX + key;
try {
String propValue = gson.toJson(disk);
savePropertyAttribute(templateId, propKey, propValue);
} catch (RuntimeException re) {
LOGGER.warn("gson marshalling of disk definition object fails: " + propKey,re);
}
}
private void savePropertyAttribute(long templateId, String key, String value) {
if ( templateDetailsDao.findDetail(templateId,key) != null) {
LOGGER.debug(String.format("detail '%s' existed for template %d, deleting.", key, templateId));
templateDetailsDao.removeDetail(templateId,key);
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("template detail for template %d to save is '%s': '%s'", templateId, key, value));
}
VMTemplateDetailVO detailVO = new VMTemplateDetailVO(templateId, key, value, false);
LOGGER.debug("Persisting template details " + detailVO.getName() + " from OVF properties for template " + templateId);
templateDetailsDao.persist(detailVO);
}
protected Void createTemplateAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback, protected Void createTemplateAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback,
CreateContext<CreateCmdResult> context) { CreateContext<CreateCmdResult> context) {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
@ -304,17 +198,14 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
DownloadAnswer answer = callback.getResult(); DownloadAnswer answer = callback.getResult();
DataObject obj = context.data; DataObject obj = context.data;
DataStore store = obj.getDataStore(); DataStore store = obj.getDataStore();
List<OVFPropertyTO> ovfProperties = answer.getOvfProperties();
List<NetworkPrerequisiteTO> networkRequirements = answer.getNetworkRequirements();
List<DatadiskTO> disks = answer.getDisks();
OVFVirtualHardwareSectionTO ovfHardwareSection = answer.getOvfHardwareSection();
List<OVFEulaSectionTO> eulaSections = answer.getEulaSections();
VMTemplateVO template = _templateDao.findById(obj.getId()); VMTemplateVO template = _templateDao.findById(obj.getId());
TemplateDataStoreVO tmpltStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(), obj.getId()); TemplateDataStoreVO tmpltStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(), obj.getId());
if (tmpltStoreVO != null) { if (tmpltStoreVO != null) {
if (tmpltStoreVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { if (tmpltStoreVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
persistExtraDetails(obj, ovfProperties, networkRequirements, disks, ovfHardwareSection, eulaSections); if (template.isDeployAsIs()) {
deployAsIsHelper.persistTemplateDeployAsIsDetails(template.getId(), answer);
}
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Template is already in DOWNLOADED state, ignore further incoming DownloadAnswer"); LOGGER.debug("Template is already in DOWNLOADED state, ignore further incoming DownloadAnswer");
} }
@ -354,7 +245,9 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
templateDaoBuilder.setChecksum(answer.getCheckSum()); templateDaoBuilder.setChecksum(answer.getCheckSum());
_templateDao.update(obj.getId(), templateDaoBuilder); _templateDao.update(obj.getId(), templateDaoBuilder);
} }
persistExtraDetails(obj, ovfProperties, networkRequirements, disks, ovfHardwareSection, eulaSections); if (template.isDeployAsIs()) {
deployAsIsHelper.persistTemplateDeployAsIsDetails(template.getId(), answer);
}
CreateCmdResult result = new CreateCmdResult(null, null); CreateCmdResult result = new CreateCmdResult(null, null);
caller.complete(result); caller.complete(result);
@ -362,76 +255,6 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
return null; return null;
} }
private void persistExtraDetails(DataObject obj, List<OVFPropertyTO> ovfProperties, List<NetworkPrerequisiteTO> networkRequirements, List<DatadiskTO> disks, OVFVirtualHardwareSectionTO ovfHardwareSection, List<OVFEulaSectionTO> eulaSections) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving %d ovf properties for template '%s' as details", ovfProperties != null ? ovfProperties.size() : 0, obj.getUuid()));
}
if (CollectionUtils.isNotEmpty(ovfProperties)) {
persistOVFProperties(ovfProperties, obj.getId());
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving %d required network requirements for template '%s' as details", networkRequirements != null ? networkRequirements.size() : 0, obj.getUuid()));
}
if (CollectionUtils.isNotEmpty(networkRequirements)) {
persistNetworkRequirements(networkRequirements, obj.getId());
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("saving %d disks definitions for template '%s' as details", disks != null ? disks.size() : 0, obj.getUuid()));
}
if (CollectionUtils.isNotEmpty(disks)) {
persistDiskDefinitions(disks, obj.getId());
}
if (CollectionUtils.isNotEmpty(eulaSections)) {
persistEulaSectionsAsTemplateDetails(eulaSections, obj.getId());
}
persistOVFHardwareSectionAsTemplateDetails(ovfHardwareSection, obj.getId());
}
private void persistEulaSectionsAsTemplateDetails(List<OVFEulaSectionTO> eulaSections, long templateId) {
CompressionUtil compressionUtil = new CompressionUtil();
for (OVFEulaSectionTO eulaSectionTO : eulaSections) {
String key = ImageStore.OVF_EULA_SECTION_PREFIX + eulaSectionTO.getIndex() + "-" + eulaSectionTO.getInfo();
byte[] compressedLicense = eulaSectionTO.getCompressedLicense();
try {
String detailValue = compressionUtil.decompressByteArary(compressedLicense);
savePropertyAttribute(templateId, key, detailValue);
} catch (IOException e) {
LOGGER.error("Could not decompress the license for template " + templateId, e);
}
}
}
/**
* Persist template details for template with ID=templateId, with name=key and value=json(object)
*/
private void persistTemplateDetailGsonEncoded(long templateId, String key, Object object) {
try {
String propValue = gson.toJson(object);
savePropertyAttribute(templateId, key, propValue);
} catch (RuntimeException re) {
LOGGER.error("gson marshalling of property object fails: " + key, re);
}
}
private void persistOVFHardwareSectionAsTemplateDetails(OVFVirtualHardwareSectionTO ovfHardwareSection, long templateId) {
if (ovfHardwareSection != null) {
if (CollectionUtils.isNotEmpty(ovfHardwareSection.getConfigurations())) {
for (OVFConfigurationTO configuration : ovfHardwareSection.getConfigurations()) {
String key = configuration.getId();
String propKey = ImageStore.OVF_HARDWARE_CONFIGURATION_PREFIX + configuration.getIndex() + "-" + key;
persistTemplateDetailGsonEncoded(templateId, propKey, configuration);
}
}
if (CollectionUtils.isNotEmpty(ovfHardwareSection.getCommonHardwareItems())) {
for (OVFVirtualHardwareItemTO item : ovfHardwareSection.getCommonHardwareItems()) {
String key = item.getResourceType().getName().trim().replaceAll("\\s","") + "-" + item.getInstanceId();
String propKey = ImageStore.OVF_HARDWARE_ITEM_PREFIX + key;
persistTemplateDetailGsonEncoded(templateId, propKey, item);
}
}
}
}
protected Void protected Void
createVolumeAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback, CreateContext<CreateCmdResult> context) { createVolumeAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback, CreateContext<CreateCmdResult> context) {
DownloadAnswer answer = callback.getResult(); DownloadAnswer answer = callback.getResult();

View File

@ -0,0 +1,15 @@
package org.apache.cloudstack.storage.image.deployasis;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.vm.VirtualMachineProfile;
import java.util.Map;
public interface DeployAsIsHelper {
void persistTemplateDeployAsIsDetails(long templateId, DownloadAnswer answer);
Map<String, String> getVirtualMachineDeployAsIsProperties(VirtualMachineProfile vmId);
String getAllocatedVirtualMachineTemplatePath(VirtualMachineProfile vm, String configuration, String destStoragePool);
String getAllocatedVirtualMachineDestinationStoragePool(VirtualMachineProfile vm);
}

View File

@ -0,0 +1,212 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.image.deployasis;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.deployasis.OVFConfigurationTO;
import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareItemTO;
import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import com.cloud.agent.api.to.deployasis.TemplateDeployAsIsInformationTO;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.deployasis.UserVmDeployAsIsDetailVO;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDao;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.utils.compression.CompressionUtil;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.vm.VirtualMachineProfile;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class DeployAsIsHelperImpl implements DeployAsIsHelper {
private static final Logger LOGGER = Logger.getLogger(DeployAsIsHelperImpl.class);
private static Gson gson;
@Inject
private TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
@Inject
private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao;
@Inject
private PrimaryDataStoreDao storagePoolDao;
@Inject
private VMTemplatePoolDao templateStoragePoolDao;
static {
GsonBuilder builder = new GsonBuilder();
builder.disableHtmlEscaping();
gson = builder.create();
}
public void persistTemplateDeployAsIsDetails(long templateId, DownloadAnswer answer) {
List<OVFPropertyTO> ovfProperties = answer.getOvfProperties();
List<OVFNetworkTO> networkRequirements = answer.getNetworkRequirements();
OVFVirtualHardwareSectionTO ovfHardwareSection = answer.getOvfHardwareSection();
List<OVFEulaSectionTO> eulaSections = answer.getEulaSections();
if (CollectionUtils.isNotEmpty(ovfProperties)) {
persistTemplateDeployAsIsInformationTOList(templateId, ovfProperties);
}
if (CollectionUtils.isNotEmpty(networkRequirements)) {
persistTemplateDeployAsIsInformationTOList(templateId, networkRequirements);
}
if (CollectionUtils.isNotEmpty(eulaSections)) {
persistTemplateDeployAsIsInformationTOList(templateId, eulaSections);
}
if (ovfHardwareSection != null) {
if (CollectionUtils.isNotEmpty(ovfHardwareSection.getConfigurations())) {
persistTemplateDeployAsIsInformationTOList(templateId, ovfHardwareSection.getConfigurations());
}
if (CollectionUtils.isNotEmpty(ovfHardwareSection.getCommonHardwareItems())) {
persistTemplateDeployAsIsInformationTOList(templateId, ovfHardwareSection.getCommonHardwareItems());
}
}
}
@Override
public Map<String, String> getVirtualMachineDeployAsIsProperties(VirtualMachineProfile vm) {
Map<String, String> map = new HashMap<>();
List<UserVmDeployAsIsDetailVO> details = userVmDeployAsIsDetailsDao.listDetails(vm.getId());
if (CollectionUtils.isNotEmpty(details)) {
for (UserVmDeployAsIsDetailVO detail : details) {
OVFPropertyTO property = templateDeployAsIsDetailsDao.findPropertyByTemplateAndKey(vm.getTemplateId(), detail.getName());
String value = property.isPassword() ? DBEncryptionUtil.decrypt(detail.getValue()) : detail.getValue();
map.put(detail.getName(), value);
}
}
return map;
}
@Override
public String getAllocatedVirtualMachineTemplatePath(VirtualMachineProfile vm, String configuration, String destStoragePool) {
StoragePoolVO storagePoolVO = storagePoolDao.findByUuid(destStoragePool);
VMTemplateStoragePoolVO tmplRef = templateStoragePoolDao.findByPoolTemplate(storagePoolVO.getId(),
vm.getTemplate().getId(), configuration);
if (tmplRef != null) {
return tmplRef.getInstallPath();
}
return null;
}
@Override
public String getAllocatedVirtualMachineDestinationStoragePool(VirtualMachineProfile vm) {
if (vm != null) {
if (CollectionUtils.isNotEmpty(vm.getDisks())) {
for (DiskTO disk : vm.getDisks()) {
if (disk.getType() == Volume.Type.ISO) {
continue;
}
DataTO data = disk.getData();
if (data != null) {
DataStoreTO dataStore = data.getDataStore();
if (dataStore != null) {
return dataStore.getUuid();
}
}
}
}
}
return null;
}
private void persistTemplateDeployAsIsInformationTOList(long templateId,
List<? extends TemplateDeployAsIsInformationTO> informationTOList) {
for (TemplateDeployAsIsInformationTO informationTO : informationTOList) {
String propKey = getKeyFromInformationTO(informationTO);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Saving property %s for template %d as detail", propKey, templateId));
}
String propValue = null;
try {
propValue = getValueFromInformationTO(informationTO);
} catch (RuntimeException re) {
LOGGER.error("gson marshalling of property object fails: " + propKey,re);
} catch (IOException e) {
LOGGER.error("Could not decompress the license for template " + templateId, e);
}
saveTemplateDeployAsIsPropertyAttribute(templateId, propKey, propValue);
}
}
private String getValueFromInformationTO(TemplateDeployAsIsInformationTO informationTO) throws IOException {
if (informationTO instanceof OVFEulaSectionTO) {
CompressionUtil compressionUtil = new CompressionUtil();
byte[] compressedLicense = ((OVFEulaSectionTO) informationTO).getCompressedLicense();
return compressionUtil.decompressByteArary(compressedLicense);
}
return gson.toJson(informationTO);
}
private String getKeyFromInformationTO(TemplateDeployAsIsInformationTO informationTO) {
if (informationTO instanceof OVFPropertyTO) {
return DeployAsIsConstants.ACS_PROPERTY_PREFIX + ((OVFPropertyTO) informationTO).getKey();
} else if (informationTO instanceof OVFNetworkTO) {
return DeployAsIsConstants.REQUIRED_NETWORK_PREFIX + ((OVFNetworkTO) informationTO).getName();
} else if (informationTO instanceof OVFConfigurationTO) {
return DeployAsIsConstants.OVF_HARDWARE_CONFIGURATION_PREFIX +
((OVFConfigurationTO) informationTO).getIndex() + "-" + ((OVFConfigurationTO) informationTO).getId();
} else if (informationTO instanceof OVFVirtualHardwareItemTO) {
String key = ((OVFVirtualHardwareItemTO) informationTO).getResourceType().getName().trim().replaceAll("\\s","")
+ "-" + ((OVFVirtualHardwareItemTO) informationTO).getInstanceId();
return DeployAsIsConstants.OVF_HARDWARE_ITEM_PREFIX + key;
} else if (informationTO instanceof OVFEulaSectionTO) {
return DeployAsIsConstants.OVF_EULA_SECTION_PREFIX + ((OVFEulaSectionTO) informationTO).getIndex() +
"-" + ((OVFEulaSectionTO) informationTO).getInfo();
}
return null;
}
private void saveTemplateDeployAsIsPropertyAttribute(long templateId, String key, String value) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Saving property %s for template %d as detail", key, templateId));
}
if (templateDeployAsIsDetailsDao.findDetail(templateId,key) != null) {
LOGGER.debug(String.format("Detail '%s' existed for template %d, deleting.", key, templateId));
templateDeployAsIsDetailsDao.removeDetail(templateId,key);
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Template detail for template %d to save is '%s': '%s'", templateId, key, value));
}
TemplateDeployAsIsDetailVO detailVO = new TemplateDeployAsIsDetailVO(templateId, key, value);
LOGGER.debug("Persisting template details " + detailVO.getName() + " from OVF properties for template " + templateId);
templateDeployAsIsDetailsDao.persist(detailVO);
}
}

View File

@ -72,4 +72,6 @@
<bean id="imageStoreDetailsUtil" class="com.cloud.storage.ImageStoreDetailsUtil" /> <bean id="imageStoreDetailsUtil" class="com.cloud.storage.ImageStoreDetailsUtil" />
<bean id="deployAsIsImageStoreHelper" class="org.apache.cloudstack.storage.image.deployasis.DeployAsIsHelperImpl" />
</beans> </beans>

View File

@ -16,9 +16,7 @@
// under the License. // under the License.
package com.cloud.hypervisor.guru; package com.cloud.hypervisor.guru;
import com.cloud.agent.api.storage.OVFPropertyTO;
import com.cloud.agent.api.to.DeployAsIsInfoTO; import com.cloud.agent.api.to.DeployAsIsInfoTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientAddressCapacityException;
@ -35,12 +33,8 @@ import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.NetworkVO;
import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSHypervisorVO;
import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOSVO;
import com.cloud.storage.ImageStore;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.storage.dao.GuestOSHypervisorDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
@ -51,10 +45,8 @@ import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmDetailConstants; import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.image.deployasis.DeployAsIsHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -65,7 +57,6 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
class VmwareVmImplementer { class VmwareVmImplementer {
private static final Logger LOGGER = Logger.getLogger(VmwareVmImplementer.class); private static final Logger LOGGER = Logger.getLogger(VmwareVmImplementer.class);
@ -89,9 +80,9 @@ class VmwareVmImplementer {
@Inject @Inject
VMTemplatePoolDao templateStoragePoolDao; VMTemplatePoolDao templateStoragePoolDao;
@Inject @Inject
VMTemplateDetailsDao templateDetailsDao;
@Inject
VmwareManager vmwareMgr; VmwareManager vmwareMgr;
@Inject
DeployAsIsHelper deployAsIsHelper;
private Boolean globalNestedVirtualisationEnabled; private Boolean globalNestedVirtualisationEnabled;
private Boolean globalNestedVPerVMEnabled; private Boolean globalNestedVPerVMEnabled;
@ -183,9 +174,7 @@ class VmwareVmImplementer {
} }
if (deployAsIs) { if (deployAsIs) {
List<OVFPropertyTO> ovfProperties = getOvfPropertyList(vm, details); setDeployAsIsInfoTO(vm, to, details);
handleOvfProperties(vm, to, details, ovfProperties);
setDeployAsIsParams(vm, to, details);
} }
setDetails(to, details); setDetails(to, details);
@ -193,44 +182,25 @@ class VmwareVmImplementer {
return to; return to;
} }
private void setDeployAsIsParams(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details) { /**
DeployAsIsInfoTO info = new DeployAsIsInfoTO(); * Set the information relevant for deploy-as-is VMs on the VM TO
*/
String configuration = null; private void setDeployAsIsInfoTO(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details) {
if (details.containsKey(VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION)) { String configuration = details.getOrDefault(VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION, null);
configuration = details.get(VmDetailConstants.DEPLOY_AS_IS_CONFIGURATION); Map<String, String> properties = deployAsIsHelper.getVirtualMachineDeployAsIsProperties(vm);
info.setDeploymentConfiguration(configuration); String destStoragePool = deployAsIsHelper.getAllocatedVirtualMachineDestinationStoragePool(vm);
} String templatePath = deployAsIsHelper.getAllocatedVirtualMachineTemplatePath(vm, configuration, destStoragePool);
DeployAsIsInfoTO info = new DeployAsIsInfoTO(templatePath, destStoragePool, properties);
// Deploy as-is disks are all allocated to the same storage pool
String deployAsIsStoreUuid = vm.getDisks().get(0).getData().getDataStore().getUuid();
StoragePoolVO storagePoolVO = storagePoolDao.findByUuid(deployAsIsStoreUuid);
VMTemplateStoragePoolVO tmplRef = templateStoragePoolDao.findByPoolTemplate(storagePoolVO.getId(), vm.getTemplate().getId(), configuration);
if (tmplRef != null) {
info.setTemplatePath(tmplRef.getInstallPath());
}
info.setDeployAsIs(true);
to.setDeployAsIsInfo(info); to.setDeployAsIsInfo(info);
} }
private void setDetails(VirtualMachineTO to, Map<String, String> details) { private void setDetails(VirtualMachineTO to, Map<String, String> details) {
Map<String, String> detailsToSend = new HashMap<>(); if (LOGGER.isTraceEnabled()) {
for (String key : details.keySet()) { for (String key : details.keySet()) {
if (key.startsWith(ImageStore.OVF_EULA_SECTION_PREFIX) ||
key.startsWith(ImageStore.OVF_HARDWARE_CONFIGURATION_PREFIX) ||
key.startsWith(ImageStore.OVF_HARDWARE_ITEM_PREFIX)) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Discarding detail for VM %s: %s => %s", to.getName(), key, details.get(key)));
}
continue;
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Detail for VM %s: %s => %s", to.getName(), key, details.get(key))); LOGGER.trace(String.format("Detail for VM %s: %s => %s", to.getName(), key, details.get(key)));
} }
detailsToSend.put(key, details.get(key));
} }
to.setDetails(detailsToSend); to.setDetails(details);
} }
private void configureDomainRouterNicsAndDetails(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details, List<NicProfile> nicProfiles) { private void configureDomainRouterNicsAndDetails(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details, List<NicProfile> nicProfiles) {
@ -318,49 +288,6 @@ class VmwareVmImplementer {
} }
} }
private void handleOvfProperties(VirtualMachineProfile vm, VirtualMachineTO to, Map<String, String> details, List<OVFPropertyTO> ovfProperties) {
if (CollectionUtils.isNotEmpty(ovfProperties)) {
removeOvfPropertiesFromDetails(ovfProperties, details);
to.setOvfProperties(ovfProperties);
}
}
private DiskTO getRootDiskTOFromVM(VirtualMachineProfile vm) {
DiskTO rootDiskTO;
List<DiskTO> rootDiskList;
rootDiskList = vm.getDisks().stream().filter(x -> x.getType() == Volume.Type.ROOT).collect(Collectors.toList());
if (rootDiskList.size() != 1) {
if (vm.getTemplate().isDeployAsIs()) {
rootDiskList = vm.getDisks().stream().filter(x -> x.getType() == null).collect(Collectors.toList());
if (rootDiskList.size() < 1) {
throw new CloudRuntimeException("Did not find a template to serve as root disk for VM " + vm.getHostName());
}
} else {
throw new CloudRuntimeException("Did not find only one root disk for VM " + vm.getHostName());
}
}
rootDiskTO = rootDiskList.get(0);
return rootDiskTO;
}
private List<OVFPropertyTO> getOvfPropertyList(VirtualMachineProfile vm, Map<String, String> details) {
List<OVFPropertyTO> ovfProperties = new ArrayList<OVFPropertyTO>();
for (String detailKey : details.keySet()) {
if (detailKey.startsWith(ImageStore.ACS_PROPERTY_PREFIX)) {
OVFPropertyTO propertyTO = templateDetailsDao.findPropertyByTemplateAndKey(vm.getTemplateId(), detailKey);
String vmPropertyKey = detailKey.replace(ImageStore.ACS_PROPERTY_PREFIX, "");
if (propertyTO == null) {
LOGGER.warn(String.format("OVF property %s not found on template, discarding", vmPropertyKey));
continue;
}
propertyTO.setKey(vmPropertyKey);
propertyTO.setValue(details.get(detailKey));
ovfProperties.add(propertyTO);
}
}
return ovfProperties;
}
private void addReservationDetails(long clusterId, Map<String, String> details) { private void addReservationDetails(long clusterId, Map<String, String> details) {
details.put(VMwareGuru.VmwareReserveCpu.key(), VMwareGuru.VmwareReserveCpu.valueIn(clusterId).toString()); details.put(VMwareGuru.VmwareReserveCpu.key(), VMwareGuru.VmwareReserveCpu.valueIn(clusterId).toString());
details.put(VMwareGuru.VmwareReserveMemory.key(), VMwareGuru.VmwareReserveMemory.valueIn(clusterId).toString()); details.put(VMwareGuru.VmwareReserveMemory.key(), VMwareGuru.VmwareReserveMemory.valueIn(clusterId).toString());
@ -408,16 +335,6 @@ class VmwareVmImplementer {
// details.put(VmDetailConstants.BOOT_TYPE, to.getBootType()); // details.put(VmDetailConstants.BOOT_TYPE, to.getBootType());
} }
/*
Remove OVF properties from details to be sent to hypervisor (avoid duplicate data)
*/
private void removeOvfPropertiesFromDetails(List<OVFPropertyTO> ovfProperties, Map<String, String> details) {
for (OVFPropertyTO propertyTO : ovfProperties) {
String key = propertyTO.getKey();
details.remove(ApiConstants.PROPERTIES + "-" + key);
}
}
/** /**
* Adds {@code 'nestedVirtualizationFlag'} value to {@code details} due to if it should be enabled or not * Adds {@code 'nestedVirtualizationFlag'} value to {@code details} due to if it should be enabled or not
* @param details vm details should not be null * @param details vm details should not be null

View File

@ -47,7 +47,6 @@ import javax.xml.datatype.XMLGregorianCalendar;
import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DeployAsIsInfoTO; import com.cloud.agent.api.to.DeployAsIsInfoTO;
import com.cloud.storage.ImageStore;
import com.cloud.agent.api.ValidateVcenterDetailsCommand; import com.cloud.agent.api.ValidateVcenterDetailsCommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.configdrive.ConfigDrive; import org.apache.cloudstack.storage.configdrive.ConfigDrive;
@ -56,7 +55,6 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
@ -180,7 +178,7 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeAnswer;
import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.storage.MigrateVolumeCommand;
import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ResizeVolumeAnswer; import com.cloud.agent.api.storage.ResizeVolumeAnswer;
@ -253,7 +251,6 @@ import com.cloud.utils.ExecutionResult;
import com.cloud.utils.NumbersUtil; import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.Ternary; import com.cloud.utils.Ternary;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.DB; import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionUtil; import com.cloud.utils.exception.ExceptionUtil;
@ -1842,14 +1839,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
DiskTO[] specDisks = vmSpec.getDisks(); DiskTO[] specDisks = vmSpec.getDisks();
DeployAsIsInfoTO deployAsIsInfo = vmSpec.getDeployAsIsInfo(); DeployAsIsInfoTO deployAsIsInfo = vmSpec.getDeployAsIsInfo();
boolean installAsIs = deployAsIsInfo != null && deployAsIsInfo.isDeployAsIs(); boolean installAsIs = deployAsIsInfo != null;
if (installAsIs && dcMo.findVm(vmInternalCSName) == null) { if (installAsIs && dcMo.findVm(vmInternalCSName) == null) {
if (s_logger.isTraceEnabled()) { if (s_logger.isTraceEnabled()) {
s_logger.trace("Deploying OVA from as is"); s_logger.trace("Deploying OVA from as is");
} }
String deployAsIsTemplate = deployAsIsInfo.getTemplatePath(); String deployAsIsTemplate = deployAsIsInfo.getTemplatePath();
String destDatastore = getDatastoreFromSpecDisks(specDisks); String destDatastore = deployAsIsInfo.getDestStoragePool();
String deploymentConfiguration = deployAsIsInfo.getDeploymentConfiguration();
vmInVcenter = _storageProcessor.cloneVMFromTemplate(deployAsIsTemplate, vmInternalCSName, destDatastore); vmInVcenter = _storageProcessor.cloneVMFromTemplate(deployAsIsTemplate, vmInternalCSName, destDatastore);
mapSpecDisksToClonedDisks(vmInVcenter, vmInternalCSName, specDisks); mapSpecDisksToClonedDisks(vmInVcenter, vmInternalCSName, specDisks);
} }
@ -1996,7 +1992,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (s_logger.isTraceEnabled()) { if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("current count(s) desired: %d/ found:%d. now adding device to device count for vApp config ISO", totalChangeDevices, hackDeviceCount)); s_logger.trace(String.format("current count(s) desired: %d/ found:%d. now adding device to device count for vApp config ISO", totalChangeDevices, hackDeviceCount));
} }
if (vmSpec.getOvfProperties() != null) { if (deployAsIsInfo != null && deployAsIsInfo.getProperties() != null) {
totalChangeDevices++; totalChangeDevices++;
} }
@ -2381,18 +2377,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// config video card // config video card
configureVideoCard(vmMo, vmSpec, vmConfigSpec); configureVideoCard(vmMo, vmSpec, vmConfigSpec);
// Set OVF properties (if available) setDeployAsIsProperties(vmMo, deployAsIsInfo, vmConfigSpec);
List<OVFPropertyTO> ovfProperties = vmSpec.getOvfProperties();
VmConfigInfo templateVappConfig;
if (ovfProperties != null) {
VirtualMachineMO templateVMmo = dcMo.findVm(deployAsIsInfo.getTemplatePath());
templateVappConfig = templateVMmo.getConfigInfo().getVAppConfig();
// Set OVF properties (if available)
if (CollectionUtils.isNotEmpty(ovfProperties)) {
s_logger.info("Copying OVF properties from template and setting them to the values the user provided");
copyVAppConfigsFromTemplate(templateVappConfig, ovfProperties, vmConfigSpec);
}
}
setBootOptions(vmSpec, bootMode, vmConfigSpec); setBootOptions(vmSpec, bootMode, vmConfigSpec);
@ -2483,26 +2468,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} }
} }
private String getDatastoreFromSpecDisks(DiskTO[] specDisks) { /**
if (specDisks.length == 0) { * Set OVF properties (if available)
return null; */
private void setDeployAsIsProperties(VirtualMachineMO vmMo, DeployAsIsInfoTO deployAsIsInfo,
VirtualMachineConfigSpec vmConfigSpec) throws Exception {
if (deployAsIsInfo != null) {
Map<String, String> properties = deployAsIsInfo.getProperties();
VmConfigInfo vAppConfig = vmMo.getConfigInfo().getVAppConfig();
s_logger.info("Copying OVF properties to the values the user provided");
setVAppPropertiesToConfigSpec(vAppConfig, properties, vmConfigSpec);
} }
Map<String, List<DiskTO>> psDisksMap = Arrays.asList(specDisks).stream()
.filter(x -> x.getType() != Volume.Type.ISO && x.getData() != null && x.getData().getDataStore() != null)
.collect(Collectors.groupingBy(x -> x.getData().getDataStore().getUuid()));
String dataStore;
if (MapUtils.isEmpty(psDisksMap)) {
s_logger.error("Could not find a destination datastore for VM volumes");
return null;
} else {
dataStore = psDisksMap.keySet().iterator().next();
if (psDisksMap.keySet().size() > 1) {
s_logger.info("Found multiple destination datastores for VM volumes, selecting " + dataStore);
}
}
return dataStore;
} }
/** /**
@ -2624,17 +2600,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
/** /**
* Set the properties section from existing vApp configuration and values set on ovfProperties * Set the properties section from existing vApp configuration and values set on ovfProperties
*/ */
protected List<VAppPropertySpec> copyVAppConfigPropertySectionFromOVF(VmConfigInfo vAppConfig, List<OVFPropertyTO> ovfProperties) { protected List<VAppPropertySpec> copyVAppConfigPropertySectionFromOVF(VmConfigInfo vAppConfig, Map<String, String> ovfProperties) {
List<VAppPropertyInfo> productFromOvf = vAppConfig.getProperty(); List<VAppPropertyInfo> productFromOvf = vAppConfig.getProperty();
List<VAppPropertySpec> specs = new ArrayList<>(); List<VAppPropertySpec> specs = new ArrayList<>();
Map<String, Pair<String, Boolean>> ovfMap = getOVFMap(ovfProperties);
for (VAppPropertyInfo info : productFromOvf) { for (VAppPropertyInfo info : productFromOvf) {
VAppPropertySpec spec = new VAppPropertySpec(); VAppPropertySpec spec = new VAppPropertySpec();
if (ovfMap.containsKey(info.getId())) { if (ovfProperties.containsKey(info.getId())) {
Pair<String, Boolean> pair = ovfMap.get(info.getId()); String value = ovfProperties.get(info.getId());
String value = pair.first(); info.setValue(value);
boolean isPassword = pair.second();
info.setValue(isPassword ? DBEncryptionUtil.decrypt(value) : value);
} }
spec.setInfo(info); spec.setInfo(info);
spec.setOperation(ArrayUpdateOperation.ADD); spec.setOperation(ArrayUpdateOperation.ADD);
@ -2662,8 +2635,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
* Set the vApp configuration to vmConfig spec, copying existing configuration from vAppConfig * Set the vApp configuration to vmConfig spec, copying existing configuration from vAppConfig
* and seting properties values from ovfProperties * and seting properties values from ovfProperties
*/ */
protected void copyVAppConfigsFromTemplate(VmConfigInfo vAppConfig, protected void setVAppPropertiesToConfigSpec(VmConfigInfo vAppConfig,
List<OVFPropertyTO> ovfProperties, Map<String, String> ovfProperties,
VirtualMachineConfigSpec vmConfig) throws Exception { VirtualMachineConfigSpec vmConfig) throws Exception {
VmConfigSpec vmConfigSpec = new VmConfigSpec(); VmConfigSpec vmConfigSpec = new VmConfigSpec();
vmConfigSpec.getEula().addAll(vAppConfig.getEula()); vmConfigSpec.getEula().addAll(vAppConfig.getEula());
@ -3009,10 +2982,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
private static void configCustomExtraOption(List<OptionValue> extraOptions, VirtualMachineTO vmSpec) { private static void configCustomExtraOption(List<OptionValue> extraOptions, VirtualMachineTO vmSpec) {
// we no longer to validation anymore // we no longer to validation anymore
for (Map.Entry<String, String> entry : vmSpec.getDetails().entrySet()) { for (Map.Entry<String, String> entry : vmSpec.getDetails().entrySet()) {
if (entry.getKey().equalsIgnoreCase(VmDetailConstants.BOOT_MODE) || if (entry.getKey().equalsIgnoreCase(VmDetailConstants.BOOT_MODE)) {
entry.getKey().startsWith(ImageStore.REQUIRED_NETWORK_PREFIX) ||
entry.getKey().startsWith(ImageStore.ACS_PROPERTY_PREFIX) ||
entry.getKey().startsWith(ImageStore.DISK_DEFINITION_PREFIX)) {
continue; continue;
} }
OptionValue newVal = new OptionValue(); OptionValue newVal = new OptionValue();

View File

@ -26,6 +26,9 @@ import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -83,6 +86,8 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
private ImageStoreDao dataStoreDao; private ImageStoreDao dataStoreDao;
@Inject @Inject
private VMTemplateDetailsDao _templateDetailsDao; private VMTemplateDetailsDao _templateDetailsDao;
@Inject
private TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
private final SearchBuilder<TemplateJoinVO> tmpltIdPairSearch; private final SearchBuilder<TemplateJoinVO> tmpltIdPairSearch;
@ -240,6 +245,8 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
if (detailsView.contains(ApiConstants.DomainDetails.all)) { if (detailsView.contains(ApiConstants.DomainDetails.all)) {
Map<String, String> details = _templateDetailsDao.listDetailsKeyPairs(template.getId()); Map<String, String> details = _templateDetailsDao.listDetailsKeyPairs(template.getId());
templateResponse.setDetails(details); templateResponse.setDetails(details);
setDeployAsIsDetails(template, templateResponse);
} }
// update tag information // update tag information
@ -272,6 +279,19 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
return templateResponse; return templateResponse;
} }
private void setDeployAsIsDetails(TemplateJoinVO template, TemplateResponse templateResponse) {
if (template.isDeployAsIs()) {
List<TemplateDeployAsIsDetailVO> deployAsIsDetails = templateDeployAsIsDetailsDao.listDetails(template.getId());
for (TemplateDeployAsIsDetailVO deployAsIsDetailVO : deployAsIsDetails) {
if (deployAsIsDetailVO.getName().startsWith(DeployAsIsConstants.OVF_HARDWARE_ITEM_PREFIX)) {
//Do not list hardware items
continue;
}
templateResponse.addDeployAsIsDetail(deployAsIsDetailVO.getName(), deployAsIsDetailVO.getValue());
}
}
}
//TODO: This is to keep compatibility with 4.1 API, where updateTemplateCmd and updateIsoCmd will return a simpler TemplateResponse //TODO: This is to keep compatibility with 4.1 API, where updateTemplateCmd and updateIsoCmd will return a simpler TemplateResponse
// compared to listTemplates and listIsos. // compared to listTemplates and listIsos.
@Override @Override

View File

@ -47,12 +47,12 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.deployasis.UserVmDeployAsIsDetailVO;
import com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDao;
import com.cloud.exception.UnsupportedServiceException; import com.cloud.exception.UnsupportedServiceException;
import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.ImageStore; import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.storage.VMTemplateDetailVO;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.affinity.AffinityGroupService;
@ -83,7 +83,7 @@ import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity;
import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao; import org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDao;
@ -507,7 +507,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Inject @Inject
private ResourceTagDao resourceTagDao; private ResourceTagDao resourceTagDao;
@Inject @Inject
private VMTemplateDetailsDao templateDetailsDao; private TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
@Inject
private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao;
private ScheduledExecutorService _executor = null; private ScheduledExecutorService _executor = null;
private ScheduledExecutorService _vmIpFetchExecutor = null; private ScheduledExecutorService _vmIpFetchExecutor = null;
@ -2503,17 +2505,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
} }
} }
for (String detailName : details.keySet()) {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("looking for vm detail '%s'", detailName));
}
if (detailName.startsWith(ImageStore.ACS_PROPERTY_PREFIX)) {
OVFPropertyTO propertyTO = templateDetailsDao.findPropertyByTemplateAndKey(vmInstance.getTemplateId(),detailName);
if (propertyTO != null && propertyTO.isPassword()) {
details.put(detailName, DBEncryptionUtil.encrypt(details.get(detailName)));
}
}
}
vmInstance.setDetails(details); vmInstance.setDetails(details);
_vmDao.saveDetails(vmInstance); _vmDao.saveDetails(vmInstance);
} }
@ -4007,11 +3998,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
vm.setDetail(VmDetailConstants.DEPLOY_VM, "true"); vm.setDetail(VmDetailConstants.DEPLOY_VM, "true");
copyDiskDetailsToVm(vm, template); persistVMDeployAsIsProperties(vm, userVmOVFPropertiesMap);
setPropertiesOnVM(vm, userVmOVFPropertiesMap);
copyNetworkRequirementsToVm(vm, template);
_vmDao.saveDetails(vm); _vmDao.saveDetails(vm);
if (!isImport) { if (!isImport) {
@ -4056,33 +4043,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}); });
} }
private void copyNetworkRequirementsToVm(UserVmVO vm, VirtualMachineTemplate template) {
if (template.isDeployAsIs()) {
List<VMTemplateDetailVO> details = templateDetailsDao.listDetailsByTemplateIdMatchingPrefix(template.getId(), ImageStore.REQUIRED_NETWORK_PREFIX);
for (VMTemplateDetailVO detail : details) {
vm.setDetail(detail.getName(), detail.getValue());
}
}
}
private void copyDiskDetailsToVm(UserVmVO vm, VirtualMachineTemplate template) {
if (template.isDeployAsIs()) {
List<VMTemplateDetailVO> details = templateDetailsDao.listDetailsByTemplateIdMatchingPrefix(template.getId(), ImageStore.DISK_DEFINITION_PREFIX);
for (VMTemplateDetailVO detail : details) {
vm.setDetail(detail.getName(), detail.getValue());
}
}
}
/** /**
* take the properties and set them on the vm. * take the properties and set them on the vm.
* consider should we be complete, and make sure all default values are copied as well if known? * consider should we be complete, and make sure all default values are copied as well if known?
* I.E. iterate over the template details as well to copy any that are not defined yet. * I.E. iterate over the template details as well to copy any that are not defined yet.
*/ */
private void setPropertiesOnVM(UserVmVO vm, Map<String, String> userVmOVFPropertiesMap) { private void persistVMDeployAsIsProperties(UserVmVO vm, Map<String, String> userVmOVFPropertiesMap) {
if (MapUtils.isNotEmpty(userVmOVFPropertiesMap)) { if (MapUtils.isNotEmpty(userVmOVFPropertiesMap)) {
for (String key : userVmOVFPropertiesMap.keySet()) { for (String key : userVmOVFPropertiesMap.keySet()) {
String detailKey = ImageStore.ACS_PROPERTY_PREFIX + key; String detailKey = key;
String value = userVmOVFPropertiesMap.get(key); String value = userVmOVFPropertiesMap.get(key);
// Sanitize boolean values to expected format and encrypt passwords // Sanitize boolean values to expected format and encrypt passwords
@ -4092,7 +4061,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} else if (value.equalsIgnoreCase("False")) { } else if (value.equalsIgnoreCase("False")) {
value = "False"; value = "False";
} else { } else {
OVFPropertyTO propertyTO = templateDetailsDao.findPropertyByTemplateAndKey(vm.getTemplateId(), key); OVFPropertyTO propertyTO = templateDeployAsIsDetailsDao.findPropertyByTemplateAndKey(vm.getTemplateId(), key);
if (propertyTO != null && propertyTO.isPassword()) { if (propertyTO != null && propertyTO.isPassword()) {
value = DBEncryptionUtil.encrypt(value); value = DBEncryptionUtil.encrypt(value);
} }
@ -4101,7 +4070,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (s_logger.isTraceEnabled()) { if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("setting property '%s' as '%s' with value '%s'", key, detailKey, value)); s_logger.trace(String.format("setting property '%s' as '%s' with value '%s'", key, detailKey, value));
} }
vm.setDetail(detailKey, value); UserVmDeployAsIsDetailVO detail = new UserVmDeployAsIsDetailVO(vm.getId(), detailKey, value);
userVmDeployAsIsDetailsDao.persist(detail);
} }
} }
} }
@ -7378,19 +7348,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
private LinkedHashMap<Integer, Long> getVmOvfNetworkMapping(DataCenter zone, Account owner, VirtualMachineTemplate template, Map<Integer, Long> vmNetworkMapping) throws InsufficientCapacityException, ResourceAllocationException { private LinkedHashMap<Integer, Long> getVmOvfNetworkMapping(DataCenter zone, Account owner, VirtualMachineTemplate template, Map<Integer, Long> vmNetworkMapping) throws InsufficientCapacityException, ResourceAllocationException {
LinkedHashMap<Integer, Long> mapping = new LinkedHashMap<>(); LinkedHashMap<Integer, Long> mapping = new LinkedHashMap<>();
if (ImageFormat.OVA.equals(template.getFormat())) { if (ImageFormat.OVA.equals(template.getFormat())) {
List<NetworkPrerequisiteTO> networkPrerequisiteTOList = List<OVFNetworkTO> OVFNetworkTOList =
templateDetailsDao.listNetworkRequirementsByTemplateId(template.getId()); templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(template.getId());
if (CollectionUtils.isNotEmpty(networkPrerequisiteTOList)) { if (CollectionUtils.isNotEmpty(OVFNetworkTOList)) {
Network lastMappedNetwork = null; Network lastMappedNetwork = null;
for (NetworkPrerequisiteTO networkPrerequisiteTO : networkPrerequisiteTOList) { for (OVFNetworkTO OVFNetworkTO : OVFNetworkTOList) {
Long networkId = vmNetworkMapping.get(networkPrerequisiteTO.getInstanceID()); Long networkId = vmNetworkMapping.get(OVFNetworkTO.getInstanceID());
if (networkId == null && lastMappedNetwork == null) { if (networkId == null && lastMappedNetwork == null) {
lastMappedNetwork = getNetworkForOvfNetworkMapping(zone, owner); lastMappedNetwork = getNetworkForOvfNetworkMapping(zone, owner);
} }
if (networkId == null) { if (networkId == null) {
networkId = lastMappedNetwork.getId(); networkId = lastMappedNetwork.getId();
} }
mapping.put(networkPrerequisiteTO.getInstanceID(), networkId); mapping.put(OVFNetworkTO.getInstanceID(), networkId);
} }
} }
} }

View File

@ -37,10 +37,10 @@ import java.util.concurrent.Executors;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.agent.api.storage.OVFEulaSectionTO; import com.cloud.agent.api.to.deployasis.OVFEulaSectionTO;
import com.cloud.agent.api.storage.OVFVirtualHardwareSectionTO; import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO;
import com.cloud.agent.api.to.DatadiskTO; import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.to.deployasis.OVFPropertyTO;
import com.cloud.storage.template.Processor; import com.cloud.storage.template.Processor;
import com.cloud.storage.template.S3TemplateDownloader; import com.cloud.storage.template.S3TemplateDownloader;
import com.cloud.storage.template.TemplateDownloader; import com.cloud.storage.template.TemplateDownloader;
@ -58,7 +58,7 @@ import com.cloud.storage.template.RawImageProcessor;
import com.cloud.storage.template.TARProcessor; import com.cloud.storage.template.TARProcessor;
import com.cloud.storage.template.VhdProcessor; import com.cloud.storage.template.VhdProcessor;
import com.cloud.storage.template.TemplateConstants; import com.cloud.storage.template.TemplateConstants;
import org.apache.cloudstack.api.net.NetworkPrerequisiteTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadCommand;
import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand;
@ -132,7 +132,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
private final long id; private final long id;
private final ResourceType resourceType; private final ResourceType resourceType;
private List<OVFPropertyTO> ovfProperties; private List<OVFPropertyTO> ovfProperties;
private List<NetworkPrerequisiteTO> networks; private List<OVFNetworkTO> networks;
private List<DatadiskTO> disks; private List<DatadiskTO> disks;
private OVFVirtualHardwareSectionTO hardwareSection; private OVFVirtualHardwareSectionTO hardwareSection;
private List<OVFEulaSectionTO> eulaSections; private List<OVFEulaSectionTO> eulaSections;
@ -239,11 +239,11 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
this.ovfProperties = ovfProperties; this.ovfProperties = ovfProperties;
} }
public List<NetworkPrerequisiteTO> getNetworks() { public List<OVFNetworkTO> getNetworks() {
return networks; return networks;
} }
public void setNetworks(List<NetworkPrerequisiteTO> networks) { public void setNetworks(List<OVFNetworkTO> networks) {
this.networks = networks; this.networks = networks;
} }