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.DetachIsoCmd; | ||||||
| import com.cloud.api.commands.ExtractIsoCmd; | import com.cloud.api.commands.ExtractIsoCmd; | ||||||
| import com.cloud.api.commands.ExtractTemplateCmd; | import com.cloud.api.commands.ExtractTemplateCmd; | ||||||
|  | import com.cloud.api.commands.PrepareTemplateCmd; | ||||||
| import com.cloud.api.commands.RegisterIsoCmd; | import com.cloud.api.commands.RegisterIsoCmd; | ||||||
| import com.cloud.api.commands.RegisterTemplateCmd; | import com.cloud.api.commands.RegisterTemplateCmd; | ||||||
| import com.cloud.exception.InternalErrorException; | import com.cloud.exception.InternalErrorException; | ||||||
| @ -39,6 +40,8 @@ public interface TemplateService { | |||||||
|     VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException; |     VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException; | ||||||
| 
 | 
 | ||||||
|     VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException; |     VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException; | ||||||
|  |      | ||||||
|  |     VirtualMachineTemplate prepareTemplate(PrepareTemplateCmd cmd) ; | ||||||
| 
 | 
 | ||||||
|     boolean detachIso(DetachIsoCmd cmd); |     boolean detachIso(DetachIsoCmd cmd); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -58,6 +58,7 @@ createSnapshotPolicy=com.cloud.api.commands.CreateSnapshotPolicyCmd;15 | |||||||
| deleteSnapshotPolicies=com.cloud.api.commands.DeleteSnapshotPoliciesCmd;15 | deleteSnapshotPolicies=com.cloud.api.commands.DeleteSnapshotPoliciesCmd;15 | ||||||
| listSnapshotPolicies=com.cloud.api.commands.ListSnapshotPoliciesCmd;15 | listSnapshotPolicies=com.cloud.api.commands.ListSnapshotPoliciesCmd;15 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| #### template commands | #### template commands | ||||||
| createTemplate=com.cloud.api.commands.CreateTemplateCmd;15 | createTemplate=com.cloud.api.commands.CreateTemplateCmd;15 | ||||||
| registerTemplate=com.cloud.api.commands.RegisterTemplateCmd;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 | updateTemplatePermissions=com.cloud.api.commands.UpdateTemplatePermissionsCmd;15 | ||||||
| listTemplatePermissions=com.cloud.api.commands.ListTemplatePermissionsCmd;15 | listTemplatePermissions=com.cloud.api.commands.ListTemplatePermissionsCmd;15 | ||||||
| extractTemplate=com.cloud.api.commands.ExtractTemplateCmd;15 | extractTemplate=com.cloud.api.commands.ExtractTemplateCmd;15 | ||||||
|  | prepareTemplate=com.cloud.api.commands.PrepareTemplateCmd;1 | ||||||
| 
 | 
 | ||||||
| #### iso commands | #### iso commands | ||||||
| attachIso=com.cloud.api.commands.AttachIsoCmd;15 | 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), | 	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), | 	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), | 	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 | 	// 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), | 	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.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
| 
 | 
 | ||||||
| import javax.ejb.Local; | import javax.ejb.Local; | ||||||
| import javax.naming.ConfigurationException; | 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.DetachIsoCmd; | ||||||
| import com.cloud.api.commands.ExtractIsoCmd; | import com.cloud.api.commands.ExtractIsoCmd; | ||||||
| import com.cloud.api.commands.ExtractTemplateCmd; | import com.cloud.api.commands.ExtractTemplateCmd; | ||||||
|  | import com.cloud.api.commands.PrepareTemplateCmd; | ||||||
| import com.cloud.api.commands.RegisterIsoCmd; | import com.cloud.api.commands.RegisterIsoCmd; | ||||||
| import com.cloud.api.commands.RegisterTemplateCmd; | import com.cloud.api.commands.RegisterTemplateCmd; | ||||||
| import com.cloud.async.AsyncJobManager; | import com.cloud.async.AsyncJobManager; | ||||||
| import com.cloud.async.AsyncJobVO; | import com.cloud.async.AsyncJobVO; | ||||||
|  | import com.cloud.configuration.Config; | ||||||
| import com.cloud.configuration.ResourceCount.ResourceType; | import com.cloud.configuration.ResourceCount.ResourceType; | ||||||
| import com.cloud.configuration.dao.ConfigurationDao; | import com.cloud.configuration.dao.ConfigurationDao; | ||||||
| import com.cloud.dc.DataCenter; | import com.cloud.dc.DataCenter; | ||||||
| @ -74,6 +78,7 @@ import com.cloud.storage.Storage.TemplateType; | |||||||
| import com.cloud.storage.StorageManager; | import com.cloud.storage.StorageManager; | ||||||
| import com.cloud.storage.StoragePool; | import com.cloud.storage.StoragePool; | ||||||
| import com.cloud.storage.StoragePoolHostVO; | import com.cloud.storage.StoragePoolHostVO; | ||||||
|  | import com.cloud.storage.StoragePoolStatus; | ||||||
| import com.cloud.storage.StoragePoolVO; | import com.cloud.storage.StoragePoolVO; | ||||||
| import com.cloud.storage.Upload; | import com.cloud.storage.Upload; | ||||||
| import com.cloud.storage.Upload.Type; | 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.ComponentLocator; | ||||||
| import com.cloud.utils.component.Inject; | import com.cloud.utils.component.Inject; | ||||||
| import com.cloud.utils.component.Manager; | import com.cloud.utils.component.Manager; | ||||||
|  | import com.cloud.utils.concurrency.NamedThreadFactory; | ||||||
| import com.cloud.utils.db.DB; | import com.cloud.utils.db.DB; | ||||||
| import com.cloud.utils.db.JoinBuilder; | import com.cloud.utils.db.JoinBuilder; | ||||||
| import com.cloud.utils.db.SearchBuilder; | import com.cloud.utils.db.SearchBuilder; | ||||||
| @ -160,6 +166,9 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe | |||||||
|     @Inject HypervisorGuruManager _hvGuruMgr; |     @Inject HypervisorGuruManager _hvGuruMgr; | ||||||
|     protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch; |     protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch; | ||||||
|      |      | ||||||
|  |     int _storagePoolMaxWaitSeconds = 3600; | ||||||
|  |     ExecutorService _preloadExecutor; | ||||||
|  |      | ||||||
|     @Inject (adapter=TemplateAdapter.class) |     @Inject (adapter=TemplateAdapter.class) | ||||||
|     protected Adapters<TemplateAdapter> _adapters; |     protected Adapters<TemplateAdapter> _adapters; | ||||||
|      |      | ||||||
| @ -220,6 +229,17 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe | |||||||
|         // FIXME: async job needs fixing |         // FIXME: async job needs fixing | ||||||
|         return extract(account, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr); |         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) { |     private Long extract(Account account, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) { | ||||||
|         String desc = "template"; |         String desc = "template"; | ||||||
| @ -328,7 +348,33 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe | |||||||
|         }else{ |         }else{ | ||||||
|             return null; |             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 |     @Override @DB | ||||||
|     public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO template, StoragePool pool) { |     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); |         List<StoragePoolHostVO> vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up); | ||||||
|          |          | ||||||
|         templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200); |         templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, _storagePoolMaxWaitSeconds); | ||||||
|         if (templateStoragePoolRef == null) { |         if (templateStoragePoolRef == null) { | ||||||
|             throw new CloudRuntimeException("Unable to acquire lock on VMTemplateStoragePool: " + templateStoragePoolRefId); |             throw new CloudRuntimeException("Unable to acquire lock on VMTemplateStoragePool: " + templateStoragePoolRefId); | ||||||
|         } |         } | ||||||
| @ -699,6 +745,8 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe | |||||||
|         HostSearch.done(); |         HostSearch.done(); | ||||||
|         HostTemplateStatesSearch.done(); |         HostTemplateStatesSearch.done(); | ||||||
|          |          | ||||||
|  |         _storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600); | ||||||
|  |         _preloadExecutor = Executors.newFixedThreadPool(8, new NamedThreadFactory("Template-Preloader")); | ||||||
|         return false; |         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); | 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 ('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