bug 3224:

multiple secondary storage, copying template between zone works
This commit is contained in:
anthony 2011-05-19 19:06:07 -07:00
parent 24e86c109e
commit 99be3718cf
15 changed files with 217 additions and 302 deletions

View File

@ -61,6 +61,7 @@ public class DownloadCommand extends AbstractDownloadCommand {
this.id = that.id;
this.description = that.description;
this.auth = that.getAuth();
this.setSecUrl(that.getSecUrl());
this.maxDownloadSizeInBytes = that.getMaxDownloadSizeInBytes();
}
@ -75,8 +76,13 @@ public class DownloadCommand extends AbstractDownloadCommand {
}
public DownloadCommand(String secUrl, String url, VirtualMachineTemplate template, String user, String passwd, Long maxDownloadSizeInBytes) {
this(secUrl, template, maxDownloadSizeInBytes);
this.setUrl(url);
super(template.getUniqueName(), url, template.getFormat(), template.getAccountId());
this.hvm = template.isRequiresHvm();
this.checksum = template.getChecksum();
this.id = template.getId();
this.description = template.getDisplayText();
this.setSecUrl(secUrl);
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
auth = new PasswordAuth(user, passwd);
}

View File

@ -1,125 +0,0 @@
/**
* 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 org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.TemplateResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
@Implementation(description="Copies an ISO file.", responseObject=TemplateResponse.class)
public class CopyIsoCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(CopyIsoCmd.class.getName());
private static final String s_name = "copyisoresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name="destzoneid", type=CommandType.LONG, required=true, description="the ID of the destination zone to which the ISO file will be copied")
private Long destZoneId;
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the ISO file")
private Long id;
@Parameter(name="sourcezoneid", type=CommandType.LONG, required=true, description="the ID of the source zone from which the ISO file will be copied")
private Long sourceZoneId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getDestinationZoneId() {
return destZoneId;
}
public Long getId() {
return id;
}
public Long getSourceZoneId() {
return sourceZoneId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getStaticName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
VirtualMachineTemplate iso = _entityMgr.findById(VirtualMachineTemplate.class, getId());
if (iso != null) {
return iso.getAccountId();
}
// bad id given, parent this command to SYSTEM so ERROR events are tracked
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public String getEventType() {
return EventTypes.EVENT_ISO_COPY;
}
@Override
public String getEventDescription() {
return "copying ISO: " + getId() + " from zone: " + getSourceZoneId() + " to zone: " + getDestinationZoneId();
}
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.Iso;
}
public Long getInstanceId() {
return getId();
}
@Override
public void execute() throws ResourceAllocationException{
try {
VirtualMachineTemplate iso = _templateService.copyIso(this);
TemplateResponse isoResponse = _responseGenerator.createIsoResponse3(iso, destZoneId);
isoResponse.setResponseName(getCommandName());
this.setResponseObject(isoResponse);
} catch (StorageUnavailableException ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
}
}
}

View File

@ -20,7 +20,6 @@ package com.cloud.template;
import java.net.URISyntaxException;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
@ -39,8 +38,6 @@ public interface TemplateService {
VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException;
VirtualMachineTemplate copyIso(CopyIsoCmd cmd) throws StorageUnavailableException, ResourceAllocationException;
VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException;
boolean detachIso(DetachIsoCmd cmd);

View File

@ -74,7 +74,7 @@ listIsos=com.cloud.api.commands.ListIsosCmd;15
registerIso=com.cloud.api.commands.RegisterIsoCmd;15
updateIso=com.cloud.api.commands.UpdateIsoCmd;15
deleteIso=com.cloud.api.commands.DeleteIsoCmd;15
copyIso=com.cloud.api.commands.CopyIsoCmd;15
copyIso=com.cloud.api.commands.CopyTemplateCmd;15
updateIsoPermissions=com.cloud.api.commands.UpdateIsoPermissionsCmd;15
listIsoPermissions=com.cloud.api.commands.ListIsoPermissionsCmd;15
extractIso=com.cloud.api.commands.ExtractIsoCmd;15

View File

@ -89,7 +89,25 @@ public class JavaStorageLayer implements StorageLayer {
return file.delete();
}
}
@Override
public boolean deleteDir(String dir) {
File Dir = new File(dir);
if ( !Dir.isDirectory() ) {
return false;
}
synchronized(dir.intern()) {
File[] files = Dir.listFiles();
for( File file : files) {
if(!file.delete() ) {
return false;
}
}
}
return true;
}
@Override
public boolean exists(String path) {
synchronized(path.intern()) {

View File

@ -147,4 +147,6 @@ public interface StorageLayer extends Manager {
* @return true if the file was set to be both world readable and writeable
*/
boolean setWorldReadableAndWriteable(File file);
boolean deleteDir(String dir);
}

View File

@ -30,7 +30,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import javax.naming.ConfigurationException;
@ -49,6 +49,7 @@ import com.cloud.agent.api.PingStorageCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
@ -95,8 +96,6 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
boolean _inSystemVM = false;
boolean _sslCopy = false;
Random _rand = new Random(System.currentTimeMillis());
DownloadManager _dlMgr;
UploadManager _upldMgr;
private String _configSslScr;
@ -219,7 +218,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
String nfsHostIp = nfsHostAddr.getHostAddress();
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, nfsHostIp);
return new Answer(cmd, true, "success");
String nfsPath = nfsHostIp + ":" + uri.getPath();
String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString();
String root = _parent + "/" + dir;
mount(root, nfsPath);
return new SecStorageSetupAnswer(dir);
} catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
s_logger.error(msg);
@ -707,6 +710,15 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
fillNetworkInformation(cmd);
if(_publicIp != null)
cmd.setPublicIpAddress(_publicIp);
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("ln -sf " + _parent + " /var/www/html/copy");
String result = command.execute();
if (result != null) {
s_logger.warn("Error in linking err=" + result);
return null;
}
return new StartupCommand[] {cmd};
}

View File

@ -390,6 +390,9 @@ public class DownloadManagerImpl implements DownloadManager {
}
File file = _storage.getFile(tmpDir + File.separator + TemplateLocation.Filename);
if ( file.exists() ) {
file.delete();
}
if (!file.createNewFile()) {
s_logger.warn("Unable to create new file: " + file.getAbsolutePath());

View File

@ -193,5 +193,7 @@ public interface StorageManager extends Manager {
boolean createStoragePool(long hostId, StoragePoolVO pool);
boolean delPoolFromHost(long hostId);
boolean delPoolFromHost(long hostId);
HostVO getSecondaryStorageHost(long zoneId, long tmpltId);
}

View File

@ -940,6 +940,21 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
return secondaryStorageHost.getStorageUrl();
}
@Override
public HostVO getSecondaryStorageHost(long zoneId, long tmpltId) {
List<HostVO> hosts = _hostDao.listSecondaryStorageHosts(zoneId);
if( hosts == null || hosts.size() == 0) {
return null;
}
for( HostVO host : hosts ) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(host.getId(), tmpltId);
if (tmpltHost != null && !tmpltHost.getDestroyed() && tmpltHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
return host;
}
}
return null;
}
@Override
public HostVO getSecondaryStorageHost(long zoneId) {
List<HostVO> hosts = _hostDao.listSecondaryStorageHosts(zoneId);

View File

@ -40,7 +40,7 @@ public interface DownloadMonitor extends Manager{
public void handleTemplateSync(HostVO host);
public void copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer)
public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer)
throws StorageUnavailableException;
/*When new host added, take a look at if there are templates needed to be downloaded for the same hypervisor as the host*/

View File

@ -19,11 +19,9 @@ package com.cloud.storage.download;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
@ -42,7 +40,6 @@ import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
@ -70,6 +67,7 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.template.TemplateConstants;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.user.Account;
@ -77,7 +75,6 @@ import com.cloud.utils.component.Inject;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmManager;
@ -113,6 +110,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
VMTemplateDao _templateDao = null;
@Inject
private AgentManager _agentMgr;
@Inject SecondaryStorageVmManager _secMgr;
@Inject
ConfigurationDao _configDao;
@Inject
@ -203,7 +201,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
@Override
public void copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException{
public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException{
boolean downloadJobExists = false;
VMTemplateHostVO destTmpltHost = null;
@ -213,6 +211,9 @@ public class DownloadMonitorImpl implements DownloadMonitor {
if (srcTmpltHost == null) {
throw new InvalidParameterValueException("Template " + template.getName() + " not associated with " + sourceServer.getName());
}
if( !_secMgr.generateSetupCommand(sourceServer.getId()) ){
return false;
}
String url = generateCopyUrl(sourceServer, srcTmpltHost);
if (url == null) {
s_logger.warn("Unable to start/resume copy of template " + template.getUniqueName() + " to " + destServer.getName() + ", no secondary storage vm in running state in source zone");
@ -232,28 +233,41 @@ public class DownloadMonitorImpl implements DownloadMonitor {
if(destTmpltHost != null) {
start();
DownloadCommand dcmd = new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
DownloadListener dl = downloadJobExists?_listenerMap.get(destTmpltHost):null;
if (dl == null) {
dl = new DownloadListener(destServer, template, _timer, _vmTemplateHostDao, destTmpltHost.getId(), this, dcmd);
}
DownloadCommand dcmd =
new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
if (downloadJobExists) {
dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART);
dl.setCurrState(destTmpltHost.getDownloadState());
}
_listenerMap.put(destTmpltHost, dl);
long result = _agentMgr.sendToSecStorage(destServer, dcmd, dl);
}
HostVO ssAhost = _agentMgr.getSSAgent(destServer);
if( ssAhost == null ) {
s_logger.warn("There is no secondary storage VM for secondary storage host " + destServer.getName());
return false;
}
DownloadListener dl = new DownloadListener(ssAhost, template, _timer, _vmTemplateHostDao, destTmpltHost.getId(), this, dcmd);
if (downloadJobExists) {
dl.setCurrState(destTmpltHost.getDownloadState());
}
DownloadListener old = null;
synchronized (_listenerMap) {
old = _listenerMap.put(destTmpltHost, dl);
}
if( old != null ) {
old.abandon();
}
long result = send(ssAhost.getId(), dcmd, dl);
if (result == -1) {
s_logger.warn("Unable to start /resume COPY of template " + template.getUniqueName() + " to " + destServer.getName());
dl.setDisconnected();
dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
} else {
return true;
}
}
return false;
}
private String generateCopyUrl(String ipAddress, String path){
private String generateCopyUrl(String ipAddress, String dir, String path){
String hostname = ipAddress;
String scheme = "http";
if (_sslCopy) {
@ -261,7 +275,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
hostname = hostname + ".realhostip.com";
scheme = "https";
}
return scheme + "://" + hostname + "/copy/" + path;
return scheme + "://" + hostname + "/copy/SecStorage/" + dir + "/" + path;
}
private String generateCopyUrl(HostVO sourceServer, VMTemplateHostVO srcTmpltHost) {
@ -272,7 +286,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
s_logger.warn("A running secondary storage vm has a null public ip?");
return null;
}
return generateCopyUrl(ssVm.getPublicIpAddress(), srcTmpltHost.getInstallPath());
return generateCopyUrl(ssVm.getPublicIpAddress(), sourceServer.getParent(), srcTmpltHost.getInstallPath());
}
VMTemplateVO tmplt = _templateDao.findById(srcTmpltHost.getTemplateId());
@ -297,11 +311,14 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
String url = sserver.getStorageUrl();
String secUrl = sserver.getStorageUrl();
if(vmTemplateHost != null) {
start();
DownloadCommand dcmd = new DownloadCommand(url, template, maxTemplateSizeInBytes);
dcmd.setUrl(vmTemplateHost.getDownloadUrl());
DownloadCommand dcmd =
new DownloadCommand(secUrl, template, maxTemplateSizeInBytes);
if (downloadJobExists) {
dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART);
}
if (vmTemplateHost.isCopy()) {
dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd);
}
@ -312,11 +329,15 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
DownloadListener dl = new DownloadListener(ssAhost, template, _timer, _vmTemplateHostDao, vmTemplateHost.getId(), this, dcmd);
if (downloadJobExists) {
dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART);
dl.setCurrState(vmTemplateHost.getDownloadState());
}
_listenerMap.put(vmTemplateHost, dl);
DownloadListener old = null;
synchronized (_listenerMap) {
old = _listenerMap.put(vmTemplateHost, dl);
}
if( old != null ) {
old.abandon();
}
long result = send(ssAhost.getId(), dcmd, dl);
if (result == -1) {
@ -361,9 +382,12 @@ public class DownloadMonitorImpl implements DownloadMonitor {
public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) {
if ((dnldStatus == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) || (dnldStatus==Status.ABANDONED)){
VMTemplateHostVO vmTemplateHost = new VMTemplateHostVO(host.getId(), template.getId());
DownloadListener oldListener = _listenerMap.get(vmTemplateHost);
DownloadListener oldListener = null;
synchronized (_listenerMap) {
oldListener = _listenerMap.remove(vmTemplateHost);
}
if (oldListener != null) {
_listenerMap.remove(vmTemplateHost);
oldListener.abandon();
}
}
@ -666,7 +690,10 @@ public class DownloadMonitorImpl implements DownloadMonitor {
_vmTemplateHostDao.listByTemplateStates(templateId, VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS, VMTemplateHostVO.Status.NOT_DOWNLOADED);
if (downloadsInProgress.size() > 0){
for (VMTemplateHostVO vmthvo: downloadsInProgress) {
DownloadListener dl = _listenerMap.get(vmthvo);
DownloadListener dl = null;
synchronized (_listenerMap) {
dl = _listenerMap.remove(vmthvo);
}
if (dl != null) {
dl.abandon();
s_logger.info("Stopping download of template " + templateId + " to storage server " + vmthvo.getHostId());

View File

@ -34,6 +34,7 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
@ -246,6 +247,9 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
Answer answer = _agentMgr.easySend(ssHostId, setupCmd);
if (answer != null && answer.getResult()) {
SecStorageSetupAnswer an = (SecStorageSetupAnswer) answer;
ssHost.setParent(an.get_dir());
_hostDao.update(ssHost.getId(), ssHost);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed secondary storage " + ssHost.getName() + " in secondary storage VM " + secStorageVm.getInstanceName());
}

View File

@ -20,9 +20,11 @@ package com.cloud.template;
import java.net.URI;
import java.util.List;
import com.cloud.dc.DataCenterVO;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StoragePool;
@ -89,31 +91,16 @@ public interface TemplateManager {
/**
* Copies a template from its current secondary storage server to the secondary storage server in the specified zone.
*
* @param templateId
* @param sourceZoneId
* @param destZoneId
* @param template
* @param srcSecHost
* @param srcZone
* @param destZone
* @return true if success
* @throws InternalErrorException
* URI uri = new URI(url); if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
* throw new IllegalArgumentException("Unsupported scheme for url: " + url); } String host = uri.getHost();
*
* try { InetAddress hostAddr = InetAddress.getByName(host); if (hostAddr.isAnyLocalAddress() ||
* hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) { throw new
* IllegalArgumentException("Illegal host specified in url"); } if (hostAddr instanceof Inet6Address) { throw
* new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")"); } } catch
* (UnknownHostException uhe) { throw new IllegalArgumentException("Unable to resolve " + host); }
*
* if (_dcDao.findById(zoneId) == null) { throw new IllegalArgumentException("Please specify a valid zone."); }
*
* VMTemplateVO template = findTemplateById(templateId);
*
* VMTemplateHostVO tmpltHostRef = findTemplateHostRef(templateId, zoneId); if (tmpltHostRef != null &&
* tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED){ throw
* new IllegalArgumentException("The template hasnt been downloaded "); }
* @throws StorageUnavailableException
* @throws ResourceAllocationException
*/
boolean copy(long userId, long templateId, long sourceZoneId, long destZoneId) throws StorageUnavailableException, ResourceAllocationException;
boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException;
/**
* Deletes a template from secondary storage servers

View File

@ -37,7 +37,6 @@ import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
@ -94,6 +93,7 @@ import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateAdapter.TemplateAdapterType;
import com.cloud.user.Account;
@ -453,50 +453,24 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
@Override
@DB
public boolean copy(long userId, long templateId, long sourceZoneId, long destZoneId) throws StorageUnavailableException, ResourceAllocationException {
HostVO srcSecHost = _storageMgr.getSecondaryStorageHost(sourceZoneId);
HostVO dstSecHost = _storageMgr.getSecondaryStorageHost(destZoneId);
DataCenterVO destZone = _dcDao.findById(destZoneId);
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
if (sourceZone == null) {
throw new InvalidParameterValueException("Please specify a valid source zone.");
}
DataCenterVO dstZone = _dcDao.findById(destZoneId);
if (dstZone == null) {
throw new InvalidParameterValueException("Please specify a valid destination zone.");
}
if (sourceZoneId == destZoneId) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
public boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException {
List<HostVO> dstSecHosts = _hostDao.listSecondaryStorageHosts(dstZone.getId());
long tmpltId = template.getId();
long dstZoneId = dstZone.getId();
if (dstSecHosts == null || dstSecHosts.isEmpty() ) {
throw new StorageUnavailableException("Destination zone is not ready", DataCenter.class, dstZone.getId());
}
if (srcSecHost == null) {
throw new StorageUnavailableException("Source zone is not ready", DataCenter.class, sourceZoneId);
}
if (dstSecHost == null) {
throw new StorageUnavailableException("Destination zone is not ready", DataCenter.class, destZoneId);
}
VMTemplateVO vmTemplate = _tmpltDao.findById(templateId);
VMTemplateHostVO srcTmpltHost = null;
srcTmpltHost = _tmpltHostDao.findByHostTemplate(srcSecHost.getId(), templateId);
if (srcTmpltHost == null || srcTmpltHost.getDestroyed() || srcTmpltHost.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
throw new InvalidParameterValueException("Please specify a template that is installed on secondary storage host: " + srcSecHost.getName());
}
AccountVO account = _accountDao.findById(vmTemplate.getAccountId());
AccountVO account = _accountDao.findById(template.getAccountId());
if (_accountMgr.resourceLimitExceeded(account, ResourceType.template)) {
ResourceAllocationException rae = new ResourceAllocationException("Maximum number of templates and ISOs for account: " + account.getAccountName() + " has been exceeded.");
rae.setResourceType("template");
throw rae;
}
// Event details
String copyEventType;
String createEventType;
if (vmTemplate.getFormat().equals(ImageFormat.ISO)){
if (template.getFormat().equals(ImageFormat.ISO)){
copyEventType = EventTypes.EVENT_ISO_COPY;
createEventType = EventTypes.EVENT_ISO_CREATE;
} else {
@ -507,80 +481,52 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
Transaction txn = Transaction.currentTxn();
txn.start();
VMTemplateHostVO dstTmpltHost = null;
try {
dstTmpltHost = _tmpltHostDao.findByHostTemplate(dstSecHost.getId(), templateId, true);
if (dstTmpltHost != null) {
dstTmpltHost = _tmpltHostDao.lockRow(dstTmpltHost.getId(), true);
if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOADED) {
if (dstTmpltHost.getDestroyed() == false) {
return true;
} else {
dstTmpltHost.setDestroyed(false);
_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
return true;
}
} else if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOAD_ERROR){
if (dstTmpltHost.getDestroyed() == true) {
dstTmpltHost.setDestroyed(false);
dstTmpltHost.setDownloadState(Status.NOT_DOWNLOADED);
dstTmpltHost.setDownloadPercent(0);
dstTmpltHost.setCopy(true);
dstTmpltHost.setErrorString("");
dstTmpltHost.setJobId(null);
_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
}
}
}
} finally {
txn.commit();
}
_tmpltDao.addTemplateToZone(vmTemplate, destZoneId);
_downloadMonitor.copyTemplate(vmTemplate, srcSecHost, dstSecHost);
if(account.getId() != Account.ACCOUNT_ID_SYSTEM){
UsageEventVO usageEvent = new UsageEventVO(copyEventType, account.getId(), destZoneId, templateId, null, null, vmTemplate.getSourceTemplateId(), srcTmpltHost.getSize());
_usageEventDao.persist(usageEvent);
}
return true;
VMTemplateHostVO srcTmpltHost = _tmpltHostDao.findByHostTemplate(srcSecHost.getId(), tmpltId);
for ( HostVO dstSecHost : dstSecHosts ) {
VMTemplateHostVO dstTmpltHost = null;
try {
dstTmpltHost = _tmpltHostDao.findByHostTemplate(dstSecHost.getId(), tmpltId, true);
if (dstTmpltHost != null) {
dstTmpltHost = _tmpltHostDao.lockRow(dstTmpltHost.getId(), true);
if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOADED) {
if (dstTmpltHost.getDestroyed() == false) {
return true;
} else {
dstTmpltHost.setDestroyed(false);
_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
return true;
}
} else if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOAD_ERROR){
if (dstTmpltHost.getDestroyed() == true) {
dstTmpltHost.setDestroyed(false);
dstTmpltHost.setDownloadState(Status.NOT_DOWNLOADED);
dstTmpltHost.setDownloadPercent(0);
dstTmpltHost.setCopy(true);
dstTmpltHost.setErrorString("");
dstTmpltHost.setJobId(null);
_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
}
}
}
} finally {
txn.commit();
}
if(_downloadMonitor.copyTemplate(template, srcSecHost, dstSecHost) ) {
_tmpltDao.addTemplateToZone(template, dstZoneId);
if(account.getId() != Account.ACCOUNT_ID_SYSTEM){
UsageEventVO usageEvent = new UsageEventVO(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltHost.getSize());
_usageEventDao.persist(usageEvent);
}
return true;
}
}
return false;
}
@Override
public VirtualMachineTemplate copyIso(CopyIsoCmd cmd) throws StorageUnavailableException, ResourceAllocationException {
Long isoId = cmd.getId();
Long userId = UserContext.current().getCallerUserId();
Long sourceZoneId = cmd.getSourceZoneId();
Long destZoneId = cmd.getDestinationZoneId();
Account account = UserContext.current().getCaller();
//Verify parameters
VMTemplateVO iso = _tmpltDao.findById(isoId);
if (iso == null) {
throw new InvalidParameterValueException("Unable to find ISO with id " + isoId);
}
boolean isIso = Storage.ImageFormat.ISO.equals(iso.getFormat());
if (!isIso) {
throw new InvalidParameterValueException("Please specify a valid ISO.");
}
//Verify account information
String errMsg = "Unable to copy ISO " + isoId;
userId = accountAndUserValidation(account, userId, null, iso, errMsg);
boolean success = copy(userId, isoId, sourceZoneId, destZoneId);
VMTemplateVO copiedIso = null;
if (success) {
copiedIso = _tmpltDao.findById(isoId);
}
return copiedIso;
}
@Override
public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException {
@ -591,28 +537,49 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
Account account = UserContext.current().getCaller();
//Verify parameters
if (sourceZoneId == destZoneId) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
}
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
if (sourceZone == null) {
throw new InvalidParameterValueException("Please specify a valid source zone.");
}
DataCenterVO dstZone = _dcDao.findById(destZoneId);
if (dstZone == null) {
throw new InvalidParameterValueException("Please specify a valid destination zone.");
}
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
throw new InvalidParameterValueException("Unable to find template with id");
}
boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
if (isIso) {
throw new InvalidParameterValueException("Please specify a valid template.");
HostVO dstSecHost = _storageMgr.getSecondaryStorageHost(destZoneId, templateId);
if ( dstSecHost != null ) {
s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecHost.getId() + " in zone " + destZoneId + " , don't need to copy");
return template;
}
HostVO srcSecHost = _storageMgr.getSecondaryStorageHost(sourceZoneId, templateId);
if ( srcSecHost == null ) {
throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId );
}
//Verify account information
String errMsg = "Unable to copy template " + templateId;
userId = accountAndUserValidation(account, userId, null, template, errMsg);
boolean success = copy(userId, templateId, sourceZoneId, destZoneId);
boolean success = copy(userId, template, srcSecHost, sourceZone, dstZone);
VMTemplateVO copiedTemplate = null;
if (success) {
copiedTemplate = _tmpltDao.findById(templateId);
return template;
} else {
s_logger.warn(errMsg);
}
return copiedTemplate;
return null;
}
@Override