Add prepareTemplate command(admin only) to allow pre-loading template into primary storage

This commit is contained in:
Kelven Yang 2011-08-08 18:36:46 -07:00
parent 455f9f642c
commit 02e64f90de
6 changed files with 143 additions and 2 deletions

View 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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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),

View File

@ -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;
}

View File

@ -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.');