mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Add prepareTemplate command(admin only) to allow pre-loading template into primary storage
This commit is contained in:
parent
455f9f642c
commit
02e64f90de
86
api/src/com/cloud/api/commands/PrepareTemplateCmd.java
Normal file
86
api/src/com/cloud/api/commands/PrepareTemplateCmd.java
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.cloud.api.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.ApiConstants;
|
||||
import com.cloud.api.BaseCmd;
|
||||
import com.cloud.api.Implementation;
|
||||
import com.cloud.api.Parameter;
|
||||
import com.cloud.api.response.ListResponse;
|
||||
import com.cloud.api.response.TemplateResponse;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@Implementation(responseObject=TemplateResponse.class, description="load template into primary storage")
|
||||
public class PrepareTemplateCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(PrepareTemplateCmd.class.getName());
|
||||
|
||||
private static final String s_name = "preparetemplateresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name=ApiConstants.ZONE_ID, required=true, type=CommandType.LONG, description="zone ID of the template to be prepared in primary storage(s).")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name=ApiConstants.TEMPLATE_ID, required=true, type=CommandType.LONG, description="template ID of the template to be prepared in primary storage(s).")
|
||||
private Long templateId;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public Long getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<TemplateResponse> response = new ListResponse<TemplateResponse>();
|
||||
|
||||
VirtualMachineTemplate vmTemplate = _templateService.prepareTemplate(this);
|
||||
List<TemplateResponse> templateResponses = _responseGenerator.createTemplateResponses(vmTemplate.getId(), zoneId, true);
|
||||
response.setResponses(templateResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import com.cloud.api.commands.DeleteTemplateCmd;
|
||||
import com.cloud.api.commands.DetachIsoCmd;
|
||||
import com.cloud.api.commands.ExtractIsoCmd;
|
||||
import com.cloud.api.commands.ExtractTemplateCmd;
|
||||
import com.cloud.api.commands.PrepareTemplateCmd;
|
||||
import com.cloud.api.commands.RegisterIsoCmd;
|
||||
import com.cloud.api.commands.RegisterTemplateCmd;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
@ -39,6 +40,8 @@ public interface TemplateService {
|
||||
VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException;
|
||||
|
||||
VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException;
|
||||
|
||||
VirtualMachineTemplate prepareTemplate(PrepareTemplateCmd cmd) ;
|
||||
|
||||
boolean detachIso(DetachIsoCmd cmd);
|
||||
|
||||
|
||||
@ -58,6 +58,7 @@ createSnapshotPolicy=com.cloud.api.commands.CreateSnapshotPolicyCmd;15
|
||||
deleteSnapshotPolicies=com.cloud.api.commands.DeleteSnapshotPoliciesCmd;15
|
||||
listSnapshotPolicies=com.cloud.api.commands.ListSnapshotPoliciesCmd;15
|
||||
|
||||
|
||||
#### template commands
|
||||
createTemplate=com.cloud.api.commands.CreateTemplateCmd;15
|
||||
registerTemplate=com.cloud.api.commands.RegisterTemplateCmd;15
|
||||
@ -68,6 +69,7 @@ listTemplates=com.cloud.api.commands.ListTemplatesCmd;15
|
||||
updateTemplatePermissions=com.cloud.api.commands.UpdateTemplatePermissionsCmd;15
|
||||
listTemplatePermissions=com.cloud.api.commands.ListTemplatePermissionsCmd;15
|
||||
extractTemplate=com.cloud.api.commands.ExtractTemplateCmd;15
|
||||
prepareTemplate=com.cloud.api.commands.PrepareTemplateCmd;1
|
||||
|
||||
#### iso commands
|
||||
attachIso=com.cloud.api.commands.AttachIsoCmd;15
|
||||
|
||||
@ -54,6 +54,7 @@ public enum Config {
|
||||
StorageStatsInterval("Storage", ManagementServer.class, String.class, "storage.stats.interval", "60000", "The interval (in milliseconds) when storage stats (per host) are retrieved from agents.", null),
|
||||
MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null),
|
||||
TotalRetries("Storage", AgentManager.class, Integer.class, "total.retries", "4", "The number of times each command sent to a host should be retried in case of failure.", null),
|
||||
StoragePoolMaxWaitSeconds("Storage", ManagementServer.class, Integer.class, "storage.pool.max.waitseconds", "3600", "Timeout (in seconds) to synchronize storage pool operations.", null),
|
||||
|
||||
// Network
|
||||
NetworkLBHaproxyStatsVisbility("Network", ManagementServer.class, String.class, "network.loadbalancer.haproxy.stats.visibility", "global", "Load Balancer(haproxy) stats visibilty, it can be global,guest-network,disabled", null),
|
||||
|
||||
@ -25,6 +25,8 @@ import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
@ -43,10 +45,12 @@ import com.cloud.api.commands.DeleteTemplateCmd;
|
||||
import com.cloud.api.commands.DetachIsoCmd;
|
||||
import com.cloud.api.commands.ExtractIsoCmd;
|
||||
import com.cloud.api.commands.ExtractTemplateCmd;
|
||||
import com.cloud.api.commands.PrepareTemplateCmd;
|
||||
import com.cloud.api.commands.RegisterIsoCmd;
|
||||
import com.cloud.api.commands.RegisterTemplateCmd;
|
||||
import com.cloud.async.AsyncJobManager;
|
||||
import com.cloud.async.AsyncJobVO;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ResourceCount.ResourceType;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.DataCenter;
|
||||
@ -74,6 +78,7 @@ import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.StoragePoolHostVO;
|
||||
import com.cloud.storage.StoragePoolStatus;
|
||||
import com.cloud.storage.StoragePoolVO;
|
||||
import com.cloud.storage.Upload;
|
||||
import com.cloud.storage.Upload.Type;
|
||||
@ -111,6 +116,7 @@ import com.cloud.utils.component.Adapters;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.JoinBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
@ -160,6 +166,9 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
@Inject HypervisorGuruManager _hvGuruMgr;
|
||||
protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
|
||||
|
||||
int _storagePoolMaxWaitSeconds = 3600;
|
||||
ExecutorService _preloadExecutor;
|
||||
|
||||
@Inject (adapter=TemplateAdapter.class)
|
||||
protected Adapters<TemplateAdapter> _adapters;
|
||||
|
||||
@ -220,6 +229,17 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
// FIXME: async job needs fixing
|
||||
return extract(account, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualMachineTemplate prepareTemplate(PrepareTemplateCmd cmd) {
|
||||
|
||||
VMTemplateVO vmTemplate = _tmpltDao.findById(cmd.getTemplateId());
|
||||
if(vmTemplate == null)
|
||||
throw new InvalidParameterValueException("Unable to find template " + cmd.getTemplateId());
|
||||
|
||||
prepareTemplateInAllStoragePools(vmTemplate, cmd.getZoneId());
|
||||
return vmTemplate;
|
||||
}
|
||||
|
||||
private Long extract(Account account, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
|
||||
String desc = "template";
|
||||
@ -328,7 +348,33 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareTemplateInAllStoragePools(final VMTemplateVO template, long zoneId) {
|
||||
List<StoragePoolVO> pools = _poolDao.listPoolsByStatus(StoragePoolStatus.Up);
|
||||
for(final StoragePoolVO pool : pools) {
|
||||
if(pool.getDataCenterId() == zoneId) {
|
||||
s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId());
|
||||
this._preloadExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
reallyRun();
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Unexpected exception ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void reallyRun() {
|
||||
s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId());
|
||||
prepareTemplateForCreate(template, pool);
|
||||
s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
s_logger.info("Skip loading template " + template.getId() + " into primary storage " + pool.getId() + " as pool zone " + pool.getDataCenterId() + " is ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO template, StoragePool pool) {
|
||||
@ -391,7 +437,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
|
||||
List<StoragePoolHostVO> vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up);
|
||||
|
||||
templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200);
|
||||
templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, _storagePoolMaxWaitSeconds);
|
||||
if (templateStoragePoolRef == null) {
|
||||
throw new CloudRuntimeException("Unable to acquire lock on VMTemplateStoragePool: " + templateStoragePoolRefId);
|
||||
}
|
||||
@ -699,6 +745,8 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
||||
HostSearch.done();
|
||||
HostTemplateStatesSearch.done();
|
||||
|
||||
_storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
|
||||
_preloadExecutor = Executors.newFixedThreadPool(8, new NamedThreadFactory("Template-Preloader"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -16,3 +16,4 @@ ALTER TABLE `cloud`.`cluster` ADD COLUMN `managed_state` varchar(32) NOT NULL D
|
||||
ALTER TABLE `cloud`.`host` MODIFY `storage_ip_address` char(40);
|
||||
|
||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.redundantrouter', 'false', 'enable/disable redundant virtual router');
|
||||
INSERT IGNORE INTO configuration VALUES ('Storage', 'DEFAULT', 'management-server', 'storage.pool.max.waitseconds', '3600', 'Timeout (in seconds) to synchronize storage pool operations.');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user