server: skip zone check for PERHOST iso during attachIso (#5270)

* server: skip zone check for PERHOST iso during attachIso

Hypervisor tools ISO - vmware-toools.iso, xs-tools.iso are marked as PERHOST in DB. They are active but not downloaded to the secondary storages and hence no template-zone entry.
Skips the template-zone check for such templates.

Fixes #5265

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* inverted check

* use constants in TemplateManager

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2021-08-09 14:02:25 +05:30 committed by GitHub
parent d9503f4d76
commit 1ccb42017f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 61 additions and 57 deletions

View File

@ -18,17 +18,17 @@ package com.cloud.template;
import java.util.List;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.deploy.DeployDestination;
import com.cloud.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.dc.DataCenterVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
@ -49,7 +49,8 @@ public interface TemplateManager {
static final ConfigKey<Integer> TemplatePreloaderPoolSize = new ConfigKey<Integer>("Advanced", Integer.class, TemplatePreloaderPoolSizeCK, "8",
"Size of the TemplateManager threadpool", false, ConfigKey.Scope.Global);
static final String VMWARE_TOOLS_ISO = "vmware-tools.iso";
static final String XS_TOOLS_ISO = "xs-tools.iso";
/**
* Prepares a template for vm creation for a certain storage pool.

View File

@ -27,11 +27,8 @@ import java.util.UUID;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.vmware.vim25.ManagedObjectReference;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
@ -75,9 +72,11 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.UriUtils;
import com.vmware.vim25.ManagedObjectReference;
public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
private static final Logger s_logger = Logger.getLogger(VmwareServerDiscoverer.class);
@ -563,7 +562,7 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer
}
private void createVmwareToolsIso() {
String isoName = "vmware-tools.iso";
String isoName = TemplateManager.VMWARE_TOOLS_ISO;
VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName);
Long id;
if (tmplt == null) {

View File

@ -257,6 +257,7 @@ import com.cloud.storage.resource.VmwareStorageProcessor;
import com.cloud.storage.resource.VmwareStorageProcessor.VmwareStorageProcessorConfigurableFields;
import com.cloud.storage.resource.VmwareStorageSubsystemCommandHandler;
import com.cloud.storage.template.TemplateProp;
import com.cloud.template.TemplateManager;
import com.cloud.utils.DateUtil;
import com.cloud.utils.ExecutionResult;
import com.cloud.utils.NumbersUtil;
@ -5352,7 +5353,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String storeUrl = cmd.getStoreUrl();
if (storeUrl == null) {
if (!cmd.getIsoPath().equalsIgnoreCase("vmware-tools.iso")) {
if (!cmd.getIsoPath().equalsIgnoreCase(TemplateManager.VMWARE_TOOLS_ISO)) {
String msg = "ISO store root url is not found in AttachIsoCommand";
s_logger.error(msg);
throw new Exception(msg);

View File

@ -95,6 +95,7 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume;
import com.cloud.storage.template.OVAProcessor;
import com.cloud.template.TemplateManager;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.exception.CloudRuntimeException;
@ -2430,7 +2431,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
storeUrl = nfsImageStore.getUrl();
}
if (storeUrl == null) {
if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) {
if (!iso.getName().equalsIgnoreCase(TemplateManager.VMWARE_TOOLS_ISO)) {
String msg = "ISO store root url is not found in AttachIsoCommand";
s_logger.error(msg);
throw new Exception(msg);

View File

@ -84,6 +84,7 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.QueryBuilder;
@ -118,7 +119,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
@Inject
private HostPodDao _podDao;
private String xenServerIsoName = "xs-tools.iso";
private String xenServerIsoName = TemplateManager.XS_TOOLS_ISO;
private String xenServerIsoDisplayText = "XenServer Tools Installer ISO (xen-pv-drv-iso)";
protected XcpServerDiscoverer() {

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.hypervisor.xenserver.resource;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@ -124,6 +126,7 @@ import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
import com.cloud.template.TemplateManager;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.ExecutionResult;
import com.cloud.utils.NumbersUtil;
@ -164,8 +167,6 @@ import com.xensource.xenapi.VLAN;
import com.xensource.xenapi.VM;
import com.xensource.xenapi.XenAPIObject;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
/**
* CitrixResourceBase encapsulates the calls to the XenServer Xapi process to
* perform the required functionalities for CloudStack.
@ -222,8 +223,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class);
protected static final HashMap<VmPowerState, PowerState> s_powerStatesTable;
private String xenServer70plusGuestToolsName = "guest-tools.iso";
private String xenServerBefore70GuestToolsName = "xs-tools.iso";
public static final String XS_TOOLS_ISO_AFTER_70 = "guest-tools.iso";
static {
s_powerStatesTable = new HashMap<VmPowerState, PowerState>();
@ -2666,11 +2666,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
* Retrieve the actual ISO 'name-label' to be used.
* We based our decision on XenServer version.
* <ul>
* <li> for XenServer 7.0+, we use {@value #xenServer70plusGuestToolsName};
* <li> for versions before 7.0, we use {@value #xenServerBefore70GuestToolsName}.
* <li> for XenServer 7.0+, we use {@value #XS_TOOLS_ISO_AFTER_70};
* <li> for versions before 7.0, we use {@value TemplateManager#XS_TOOLS_ISO}.
* </ul>
*
* For XCP we always use {@value #xenServerBefore70GuestToolsName}.
*/
protected String getActualIsoTemplate(Connection conn) throws XenAPIException, XmlRpcException {
Host host = Host.getByUuid(conn, _host.getUuid());
@ -2680,9 +2679,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
String[] items = xenVersion.split("\\.");
if ((xenBrand.equals("XenServer") || xenBrand.equals("XCP-ng")) && Integer.parseInt(items[0]) >= 7) {
return xenServer70plusGuestToolsName;
return XS_TOOLS_ISO_AFTER_70;
}
return xenServerBefore70GuestToolsName;
return TemplateManager.XS_TOOLS_ISO;
}
public String getLabel() {

View File

@ -29,6 +29,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.template.TemplateManager;
@RunWith(MockitoJUnitRunner.class)
public class XcpServerDiscovererTest {
@ -42,13 +43,13 @@ public class XcpServerDiscovererTest {
@Test
public void createXenServerToolsIsoEntryInDatabaseTestNoEntryFound() {
Mockito.when(vmTemplateDao.findByTemplateName("xs-tools.iso")).thenReturn(null);
Mockito.when(vmTemplateDao.findByTemplateName(TemplateManager.XS_TOOLS_ISO)).thenReturn(null);
Mockito.when(vmTemplateDao.getNextInSequence(Long.class, "id")).thenReturn(1L);
xcpServerDiscoverer.createXenServerToolsIsoEntryInDatabase();
InOrder inOrder = Mockito.inOrder(vmTemplateDao);
inOrder.verify(vmTemplateDao).findByTemplateName("xs-tools.iso");
inOrder.verify(vmTemplateDao).findByTemplateName(TemplateManager.XS_TOOLS_ISO);
inOrder.verify(vmTemplateDao).getNextInSequence(Long.class, "id");
inOrder.verify(vmTemplateDao).persist(Mockito.any(VMTemplateVO.class));
}
@ -56,13 +57,13 @@ public class XcpServerDiscovererTest {
@Test
public void createXenServerToolsIsoEntryInDatabaseTestEntryAlreadyExist() {
VMTemplateVO vmTemplateVOMock = Mockito.mock(VMTemplateVO.class);
Mockito.when(vmTemplateDao.findByTemplateName("xs-tools.iso")).thenReturn(vmTemplateVOMock);
Mockito.when(vmTemplateDao.findByTemplateName(TemplateManager.XS_TOOLS_ISO)).thenReturn(vmTemplateVOMock);
Mockito.when(vmTemplateVOMock.getId()).thenReturn(1L);
xcpServerDiscoverer.createXenServerToolsIsoEntryInDatabase();
InOrder inOrder = Mockito.inOrder(vmTemplateDao, vmTemplateVOMock);
inOrder.verify(vmTemplateDao).findByTemplateName("xs-tools.iso");
inOrder.verify(vmTemplateDao).findByTemplateName(TemplateManager.XS_TOOLS_ISO);
inOrder.verify(vmTemplateDao, Mockito.times(0)).getNextInSequence(Long.class, "id");
inOrder.verify(vmTemplateVOMock).setTemplateType(TemplateType.PERHOST);
inOrder.verify(vmTemplateVOMock).setUrl(null);

View File

@ -42,6 +42,7 @@ import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.SRType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.StorageResourceType;
import com.cloud.template.TemplateManager;
import com.cloud.utils.script.Script;
import com.xensource.xenapi.Connection;
import com.xensource.xenapi.Host;
@ -149,7 +150,7 @@ public class CitrixResourceBaseTest {
String returnedIsoTemplateName = citrixResourceBase.getActualIsoTemplate(connectionMock);
Assert.assertEquals("xs-tools.iso", returnedIsoTemplateName);
Assert.assertEquals(TemplateManager.XS_TOOLS_ISO, returnedIsoTemplateName);
}
@Test
@ -159,7 +160,7 @@ public class CitrixResourceBaseTest {
String returnedIsoTemplateName = citrixResourceBase.getActualIsoTemplate(connectionMock);
Assert.assertEquals("xs-tools.iso", returnedIsoTemplateName);
Assert.assertEquals(TemplateManager.XS_TOOLS_ISO, returnedIsoTemplateName);
}
@Test
@ -169,7 +170,7 @@ public class CitrixResourceBaseTest {
String returnedIsoTemplateName = citrixResourceBase.getActualIsoTemplate(connectionMock);
Assert.assertEquals("guest-tools.iso", returnedIsoTemplateName);
Assert.assertEquals(CitrixResourceBase.XS_TOOLS_ISO_AFTER_70, returnedIsoTemplateName);
}
@Test
@ -179,7 +180,7 @@ public class CitrixResourceBaseTest {
String returnedIsoTemplateName = citrixResourceBase.getActualIsoTemplate(connectionMock);
Assert.assertEquals("guest-tools.iso", returnedIsoTemplateName);
Assert.assertEquals(CitrixResourceBase.XS_TOOLS_ISO_AFTER_70, returnedIsoTemplateName);
}
@Test

View File

@ -31,8 +31,6 @@ import java.util.stream.Stream;
import javax.inject.Inject;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.vm.VirtualMachineManager;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
@ -217,6 +215,7 @@ import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.StoragePoolTagsDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.template.VirtualMachineTemplate.State;
@ -242,6 +241,7 @@ import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.UserVmDao;
@ -3618,7 +3618,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
SearchCriteria<TemplateJoinVO> zoneSc = _templateJoinDao.createSearchCriteria();
zoneSc.addOr("dataCenterId", SearchCriteria.Op.EQ, zoneId);
zoneSc.addOr("dataStoreScope", SearchCriteria.Op.EQ, ScopeType.REGION);
// handle the case where xs-tools.iso and vmware-tools.iso do not
// handle the case where TemplateManager.VMWARE_TOOLS_ISO and TemplateManager.VMWARE_TOOLS_ISO do not
// have data_center information in template_view
SearchCriteria<TemplateJoinVO> isoPerhostSc = _templateJoinDao.createSearchCriteria();
isoPerhostSc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

View File

@ -26,15 +26,7 @@ import java.util.Set;
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.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.ChildTemplateResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
@ -43,13 +35,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.ApiResponseHelper;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.TemplateType;
@ -369,7 +368,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
isoResponse.setCreated(iso.getCreatedOnStore());
isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable());
if (iso.getTemplateType() == TemplateType.PERHOST) {
// for xs-tools.iso and vmware-tools.iso, we didn't download, but is ready to use.
// for TemplateManager.XS_TOOLS_ISO and TemplateManager.VMWARE_TOOLS_ISO, we didn't download, but is ready to use.
isoResponse.setReady(true);
} else {
isoResponse.setReady(iso.getState() == ObjectInDataStoreStateMachine.State.Ready);

View File

@ -137,9 +137,9 @@ import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectManager;
import com.cloud.storage.DataStoreRole;
@ -300,7 +300,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Inject
private EndPointSelector selector;
private TemplateAdapter getAdapter(HypervisorType type) {
TemplateAdapter adapter = null;
if (type == HypervisorType.BareMetal) {
@ -1204,10 +1203,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
throw new InvalidParameterValueException("Unable to find an ISO with id " + isoId);
}
long dcId = vm.getDataCenterId();
VMTemplateZoneVO exists = _tmpltZoneDao.findByZoneTemplate(dcId, isoId);
if (null == exists) {
throw new InvalidParameterValueException("ISO is not available in the zone the VM is in.");
if (!TemplateType.PERHOST.equals(iso.getTemplateType())) {
VMTemplateZoneVO exists = _tmpltZoneDao.findByZoneTemplate(vm.getDataCenterId(), isoId);
if (null == exists) {
throw new InvalidParameterValueException("ISO is not available in the zone the VM is in.");
}
}
// check permissions
@ -1224,11 +1224,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
}
if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer) {
if (XS_TOOLS_ISO.equals(iso.getUniqueName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer) {
throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType());
}
if ("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) {
if (VMWARE_TOOLS_ISO.equals(iso.getUniqueName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) {
throw new InvalidParameterValueException("Cannot attach VMware tools drivers to incompatible hypervisor " + vm.getHypervisorType());
}
boolean result = attachISOToVM(vmId, userId, isoId, true, forced);

View File

@ -16,9 +16,9 @@
// under the License.
package com.cloud.api.query.dao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.Storage;
import com.cloud.user.Account;
import java.util.Date;
import java.util.Map;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.junit.Assert;
import org.junit.Before;
@ -27,13 +27,14 @@ import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.TemplateJoinVO;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Date;
import java.util.Map;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.Storage;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
@RunWith(PowerMockRunner.class)
@PrepareForTest(ApiDBUtils.class)
@ -47,7 +48,7 @@ public class TemplateJoinDaoImplTest extends GenericDaoBaseWithTagInformationBas
//TemplateJoinVO fields
private String uuid = "1234567890abc";
private String name = "xs-tools.iso";
private String name = TemplateManager.XS_TOOLS_ISO;
private String displayText = "xen-pv-drv-iso";
private boolean publicTemplate = true;
private Date created = new Date();