Refactor DownloadMonitorImpl code, move some functionalities to

TemplateServiceImpl and VolumeServiceImpl.
This commit is contained in:
Min Chen 2013-04-11 18:09:42 -07:00
parent 582a1f0539
commit bb64672715
51 changed files with 1174 additions and 999 deletions

View File

@ -18,16 +18,16 @@ package com.cloud.agent.api;
import java.util.Map;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
public class ModifyStoragePoolAnswer extends Answer {
StoragePoolInfo poolInfo;
Map<String, TemplateInfo> templateInfo;
Map<String, TemplateProp> templateInfo;
protected ModifyStoragePoolAnswer() {
}
public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map<String, TemplateInfo> tInfo) {
public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map<String, TemplateProp> tInfo) {
super(cmd);
this.result = true;
this.poolInfo = new StoragePoolInfo(null,
@ -46,11 +46,11 @@ public class ModifyStoragePoolAnswer extends Answer {
}
public Map<String, TemplateInfo> getTemplateInfo() {
public Map<String, TemplateProp> getTemplateInfo() {
return templateInfo;
}
public void setTemplateInfo(Map<String, TemplateInfo> templateInfo) {
public void setTemplateInfo(Map<String, TemplateProp> templateInfo) {
this.templateInfo = templateInfo;
}

View File

@ -22,13 +22,13 @@ import java.util.Map;
import com.cloud.host.Host;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
public class StartupStorageCommand extends StartupCommand {
String parent;
Map<String, TemplateInfo> templateInfo;
Map<String, TemplateProp> templateInfo;
long totalSize;
StoragePoolInfo poolInfo;
Storage.StorageResourceType resourceType;
@ -40,7 +40,7 @@ public class StartupStorageCommand extends StartupCommand {
super(Host.Type.Storage);
}
public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map<String, TemplateInfo> info) {
public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map<String, TemplateProp> info) {
super(Host.Type.Storage);
this.parent = parent;
this.totalSize = totalSize;
@ -50,7 +50,7 @@ public class StartupStorageCommand extends StartupCommand {
}
public StartupStorageCommand(String parent, StoragePoolType fsType, Map<String, TemplateInfo> templateInfo, StoragePoolInfo poolInfo) {
public StartupStorageCommand(String parent, StoragePoolType fsType, Map<String, TemplateProp> templateInfo, StoragePoolInfo poolInfo) {
super(Host.Type.Storage);
this.parent = parent;
this.templateInfo = templateInfo;
@ -79,11 +79,11 @@ public class StartupStorageCommand extends StartupCommand {
return totalSize;
}
public Map<String, TemplateInfo> getTemplateInfo() {
public Map<String, TemplateProp> getTemplateInfo() {
return templateInfo;
}
public void setTemplateInfo(Map<String, TemplateInfo> templateInfo) {
public void setTemplateInfo(Map<String, TemplateProp> templateInfo) {
this.templateInfo = templateInfo;
}

View File

@ -19,27 +19,27 @@ package com.cloud.agent.api.storage;
import java.util.Map;
import com.cloud.agent.api.Answer;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
public class ListTemplateAnswer extends Answer {
private String secUrl;
private Map<String, TemplateInfo> templateInfos;
private Map<String, TemplateProp> templateInfos;
public ListTemplateAnswer() {
}
public ListTemplateAnswer(String secUrl, Map<String, TemplateInfo> templateInfos) {
public ListTemplateAnswer(String secUrl, Map<String, TemplateProp> templateInfos) {
super(null, true, "success");
this.setSecUrl(secUrl);
this.templateInfos = templateInfos;
}
public Map<String, TemplateInfo> getTemplateInfo() {
public Map<String, TemplateProp> getTemplateInfo() {
return templateInfos;
}
public void setTemplateInfo(Map<String, TemplateInfo> templateInfos) {
public void setTemplateInfo(Map<String, TemplateProp> templateInfos) {
this.templateInfos = templateInfos;
}

View File

@ -19,27 +19,27 @@ package com.cloud.agent.api.storage;
import java.util.Map;
import com.cloud.agent.api.Answer;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
public class ListVolumeAnswer extends Answer {
private String secUrl;
private Map<Long, TemplateInfo> templateInfos;
private Map<Long, TemplateProp> templateInfos;
public ListVolumeAnswer() {
}
public ListVolumeAnswer(String secUrl, Map<Long, TemplateInfo> templateInfos) {
public ListVolumeAnswer(String secUrl, Map<Long, TemplateProp> templateInfos) {
super(null, true, "success");
this.setSecUrl(secUrl);
this.templateInfos = templateInfos;
}
public Map<Long, TemplateInfo> getTemplateInfo() {
public Map<Long, TemplateProp> getTemplateInfo() {
return templateInfos;
}
public void setTemplateInfo(Map<Long, TemplateInfo> templateInfos) {
public void setTemplateInfo(Map<Long, TemplateProp> templateInfos) {
this.templateInfos = templateInfos;
}

View File

@ -16,7 +16,7 @@
// under the License.
package com.cloud.storage.template;
public class TemplateInfo {
public class TemplateProp {
String templateName;
String installPath;
long size;
@ -25,11 +25,11 @@ public class TemplateInfo {
boolean isPublic;
boolean isCorrupted;
protected TemplateInfo() {
protected TemplateProp() {
}
public TemplateInfo(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) {
public TemplateProp(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) {
this.templateName = templateName;
this.installPath = installPath;
this.size = size;
@ -38,7 +38,7 @@ public class TemplateInfo {
this.isCorrupted = isCorrupted;
}
public TemplateInfo(String templateName, String installPath, boolean isPublic, boolean isCorrupted) {
public TemplateProp(String templateName, String installPath, boolean isPublic, boolean isCorrupted) {
this(templateName, installPath, 0, 0, isPublic, isCorrupted);
}

View File

@ -36,7 +36,7 @@ import com.cloud.exception.StorageUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
public interface TemplateService {
public interface TemplateApiService {
VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException;

View File

@ -65,7 +65,7 @@ import com.cloud.storage.DataStoreProviderApiService;
import com.cloud.storage.StorageService;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.snapshot.SnapshotService;
import com.cloud.template.TemplateService;
import com.cloud.template.TemplateApiService;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.DomainService;
@ -106,7 +106,7 @@ public abstract class BaseCmd {
@Inject public VolumeApiService _volumeService;
@Inject public ResourceService _resourceService;
@Inject public NetworkService _networkService;
@Inject public TemplateService _templateService;
@Inject public TemplateApiService _templateService;
@Inject public SecurityGroupService _securityGroupService;
@Inject public SnapshotService _snapshotService;
@Inject public ConsoleProxyService _consoleProxyService;

View File

@ -744,7 +744,7 @@
<bean id="imageDataManagerImpl" class="org.apache.cloudstack.storage.image.manager.ImageDataManagerImpl" />
<bean id="imageStoreHelper" class="org.apache.cloudstack.storage.image.datastore.ImageStoreHelper" />
<bean id="imageFormatHelper" class="org.apache.cloudstack.storage.image.format.ImageFormatHelper" />
<bean id="imageServiceImpl" class="org.apache.cloudstack.storage.image.ImageServiceImpl" />
<bean id="templateServiceImpl" class="org.apache.cloudstack.storage.image.TemplateServiceImpl" />
<bean id="iso" class="org.apache.cloudstack.engine.subsystem.api.storage.type.Iso" />
<bean id="networkFileSystem" class="org.apache.cloudstack.storage.datastore.type.NetworkFileSystem" />
<bean id="networkRestService" class="org.apache.cloudstack.engine.rest.service.api.NetworkRestService" />

View File

@ -105,7 +105,7 @@ import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.serializer.GsonHelper;
import com.cloud.storage.Volume;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DiskProfile;
@ -765,7 +765,7 @@ public class HypervResource extends ServerResourceBase implements ServerResource
try {
StorageFilerTO pool = cmd.getPool();
s_logger.info("Primary storage pool details: " + pool.getHost() + " " + pool.getPath());
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
// FIXME: get the actual storage capacity and storage stats of CSV volume
// by running powershell cmdlet. This hardcoding just for prototype.
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,

View File

@ -60,7 +60,7 @@ import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.UploadManager;
import com.cloud.storage.template.UploadManagerImpl;
import com.cloud.utils.NumbersUtil;
@ -650,7 +650,7 @@ public class CifsSecondaryStorageResource extends ServerResourceBase implements
return null;
}*/
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap<String, TemplateInfo>());
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap<String, TemplateProp>());
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
cmd.setIqn(null);

View File

@ -48,7 +48,7 @@ import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.component.ComponentContext;
public class LocalSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource {
@ -109,7 +109,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
private Answer execute(ListTemplateCommand cmd) {
String root = getRootDir();
Map<String, TemplateInfo> templateInfos = _dlMgr.gatherTemplateInfo(root);
Map<String, TemplateProp> templateInfos = _dlMgr.gatherTemplateInfo(root);
return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos);
}

View File

@ -100,7 +100,7 @@ import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.TemplateLocation;
import com.cloud.storage.template.UploadManager;
import com.cloud.storage.template.UploadManagerImpl;
@ -1073,12 +1073,12 @@ SecondaryStorageResource {
}
}
Map<String, TemplateInfo> swiftListTemplate(SwiftTO swift) {
Map<String, TemplateProp> swiftListTemplate(SwiftTO swift) {
String[] containers = swiftList(swift, "", "");
if (containers == null) {
return null;
}
Map<String, TemplateInfo> tmpltInfos = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tmpltInfos = new HashMap<String, TemplateProp>();
for( String container : containers) {
if ( container.startsWith("T-")) {
String ldir = _tmpltDir + "/" + UUID.randomUUID().toString();
@ -1095,7 +1095,7 @@ SecondaryStorageResource {
s_logger.warn("Unable to load template location " + ldir + " due to " + e.toString(), e);
continue;
}
TemplateInfo tInfo = loc.getTemplateInfo();
TemplateProp tInfo = loc.getTemplateInfo();
tInfo.setInstallPath(container);
tmpltInfos.put(tInfo.getTemplateName(), tInfo);
loc.purge();
@ -1111,11 +1111,11 @@ SecondaryStorageResource {
return new Answer(cmd, true, null);
}
if (cmd.getSwift() != null) {
Map<String, TemplateInfo> templateInfos = swiftListTemplate(cmd.getSwift());
Map<String, TemplateProp> templateInfos = swiftListTemplate(cmd.getSwift());
return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos);
} else {
String root = getRootDir(cmd.getSecUrl());
Map<String, TemplateInfo> templateInfos = _dlMgr.gatherTemplateInfo(root);
Map<String, TemplateProp> templateInfos = _dlMgr.gatherTemplateInfo(root);
return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos);
}
}
@ -1126,7 +1126,7 @@ SecondaryStorageResource {
}
String root = getRootDir(cmd.getSecUrl());
Map<Long, TemplateInfo> templateInfos = _dlMgr.gatherVolumeInfo(root);
Map<Long, TemplateProp> templateInfos = _dlMgr.gatherVolumeInfo(root);
return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos);
}

View File

@ -91,13 +91,13 @@ public interface DownloadManager extends Manager {
/**
* @return list of template info for installed templates
*/
public Map<String, TemplateInfo> gatherTemplateInfo(String templateDir);
public Map<String, TemplateProp> gatherTemplateInfo(String templateDir);
/**
/**
* @return list of volume info for installed volumes
*/
public Map<Long, TemplateInfo> gatherVolumeInfo(String volumeDir);
public Map<Long, TemplateProp> gatherVolumeInfo(String volumeDir);
}

View File

@ -717,8 +717,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
}
@Override
public Map<String, TemplateInfo> gatherTemplateInfo(String rootDir) {
Map<String, TemplateInfo> result = new HashMap<String, TemplateInfo>();
public Map<String, TemplateProp> gatherTemplateInfo(String rootDir) {
Map<String, TemplateProp> result = new HashMap<String, TemplateProp>();
String templateDir = rootDir + File.separator + _templateDir;
if (! _storage.exists(templateDir)) {
@ -741,7 +741,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
continue;
}
TemplateInfo tInfo = loc.getTemplateInfo();
TemplateProp tInfo = loc.getTemplateInfo();
if ((tInfo.size == tInfo.physicalSize) && (tInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) {
try {
@ -774,8 +774,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
}
@Override
public Map<Long, TemplateInfo> gatherVolumeInfo(String rootDir) {
Map<Long, TemplateInfo> result = new HashMap<Long, TemplateInfo>();
public Map<Long, TemplateProp> gatherVolumeInfo(String rootDir) {
Map<Long, TemplateProp> result = new HashMap<Long, TemplateProp>();
String volumeDir = rootDir + File.separator + _volumeDir;
if (! _storage.exists(volumeDir)) {
@ -798,7 +798,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
continue;
}
TemplateInfo vInfo = loc.getTemplateInfo();
TemplateProp vInfo = loc.getTemplateInfo();
if ((vInfo.size == vInfo.physicalSize) && (vInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) {
try {

View File

@ -156,8 +156,8 @@ public class TemplateLocation {
return true;
}
public TemplateInfo getTemplateInfo() {
TemplateInfo tmplInfo = new TemplateInfo();
public TemplateProp getTemplateInfo() {
TemplateProp tmplInfo = new TemplateProp();
tmplInfo.id = Long.parseLong(_props.getProperty("id"));
tmplInfo.installPath = _templatePath + File.separator + _props.getProperty("filename");
if (_resourceType == ResourceType.VOLUME){

View File

@ -20,10 +20,16 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
public interface ImageService {
import com.cloud.hypervisor.Hypervisor.HypervisorType;
public interface TemplateService {
AsyncCallFuture<CommandResult> createTemplateAsync(TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> deleteTemplateAsync(TemplateInfo template);
void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId);
void handleTemplateSync(DataStore store);
}

View File

@ -25,13 +25,13 @@ import com.cloud.exception.ConcurrentOperationException;
public interface VolumeService {
public class VolumeApiResult extends CommandResult {
private final VolumeInfo volume;
public VolumeApiResult(VolumeInfo volume) {
this.volume = volume;
}
public VolumeInfo getVolume() {
return this.volume;
}
@ -39,16 +39,16 @@ public interface VolumeService {
/**
* Creates the volume based on the given criteria
*
*
* @param cmd
*
*
* @return the volume object
*/
AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, DataStore store);
/**
* Delete volume
*
*
* @param volumeId
* @return
* @throws ConcurrentOperationException
@ -56,12 +56,12 @@ public interface VolumeService {
AsyncCallFuture<VolumeApiResult> expungeVolumeAsync(VolumeInfo volume);
/**
*
*
*/
boolean cloneVolume(long volumeId, long baseVolId);
/**
*
*
*/
AsyncCallFuture<VolumeApiResult> createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot);
@ -74,7 +74,9 @@ public interface VolumeService {
boolean destroyVolume(long volumeId) throws ConcurrentOperationException;
AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store);
AsyncCallFuture<VolumeApiResult> resize(VolumeInfo volume);
void handleVolumeSync(DataStore store);
}

View File

@ -30,7 +30,5 @@ public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, Lo
public List<SnapshotDataStoreVO> listByStoreId(long id);
public List<SnapshotDataStoreVO> listLiveByStoreId(long id);
public void deletePrimaryRecordsForStore(long id);
}

View File

@ -23,18 +23,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.fsm.StateDao;
public interface TemplateDataStoreDao extends GenericDao<TemplateDataStoreVO, Long>, StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Event, DataObjectInStore> {
public List<TemplateDataStoreVO> listByStoreId(long id);
public List<TemplateDataStoreVO> listLiveByStoreId(long id);
public List<TemplateDataStoreVO> listByStoreId(long id);
public void deletePrimaryRecordsForStore(long id);
List<TemplateDataStoreVO> listByTemplateStoreStatus(long templateId, long storeId, State... states);
List<TemplateDataStoreVO> listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status);
TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId);
}

View File

@ -291,6 +291,12 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
return this.state;
}
public void setState(ObjectInDataStoreStateMachine.State state) {
this.state = state;
}
public long getUpdatedCount() {
return this.updatedCount;
}

View File

@ -22,6 +22,7 @@ import java.util.List;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.fsm.StateDao;
@ -29,7 +30,9 @@ public interface VolumeDataStoreDao extends GenericDao<VolumeDataStoreVO, Long>,
public List<VolumeDataStoreVO> listByStoreId(long id);
public List<VolumeDataStoreVO> listLiveByStoreId(long id);
public void deletePrimaryRecordsForStore(long id);
public VolumeDataStoreVO findByVolumeId(long volumeId);
public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId);
}

View File

@ -203,14 +203,14 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
this.state = ObjectInDataStoreStateMachine.State.Allocated;
}
public VolumeDataStoreVO(long hostId, long volumeId, long zoneId, Date lastUpdated,
public VolumeDataStoreVO(long hostId, long volumeId, Date lastUpdated,
int downloadPercent, Status downloadState,
String localDownloadPath, String errorString, String jobId,
String installPath, String downloadUrl, String checksum, ImageFormat format) {
//super();
this.dataStoreId = hostId;
this.volumeId = volumeId;
this.zoneId = zoneId;
//this.zoneId = zoneId;
this.lastUpdated = lastUpdated;
this.downloadPercent = downloadPercent;
this.downloadState = downloadState;

View File

@ -1,147 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.image;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.datastore.DataObjectManager;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.utils.fsm.NoTransitionException;
@Component
public class ImageServiceImpl implements ImageService {
private static final Logger s_logger = Logger.getLogger(ImageServiceImpl.class);
@Inject
ObjectInDataStoreManager objectInDataStoreMgr;
@Inject
DataObjectManager dataObjectMgr;
class CreateTemplateContext<T> extends AsyncRpcConext<T> {
final TemplateInfo srcTemplate;
final DataStore store;
final AsyncCallFuture<CommandResult> future;
final DataObject templateOnStore;
public CreateTemplateContext(AsyncCompletionCallback<T> callback, TemplateInfo srcTemplate,
AsyncCallFuture<CommandResult> future,
DataStore store,
DataObject templateOnStore
) {
super(callback);
this.srcTemplate = srcTemplate;
this.future = future;
this.store = store;
this.templateOnStore = templateOnStore;
}
}
@Override
public AsyncCallFuture<CommandResult> createTemplateAsync(
TemplateInfo template, DataStore store) {
TemplateObject to = (TemplateObject) template;
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
// persist template_store_ref entry
DataObject templateOnStore = store.create(template);
// update template_store_ref state
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested);
CreateTemplateContext<CommandResult> context = new CreateTemplateContext<CommandResult>(null,
template,
future,
store,
templateOnStore
);
AsyncCallbackDispatcher<ImageServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(templateOnStore, caller);
return future;
}
protected Void createTemplateCallback(AsyncCallbackDispatcher<ImageServiceImpl, CreateCmdResult> callback,
CreateTemplateContext<CreateCmdResult> context) {
TemplateObject template = (TemplateObject)context.srcTemplate;
AsyncCallFuture<CommandResult> future = context.future;
CommandResult result = new CommandResult();
DataObject templateOnStore = context.templateOnStore;
CreateCmdResult callbackResult = callback.getResult();
if (callbackResult.isFailed()) {
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
template.stateTransit(TemplateEvent.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to update template state", e);
}
result.setResult(callbackResult.getResult());
future.complete(result);
return null;
}
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
template.stateTransit(TemplateEvent.OperationSucceeded);
} catch (NoTransitionException e) {
s_logger.debug("Failed to transit state", e);
result.setResult(e.toString());
future.complete(result);
return null;
}
future.complete(result);
return null;
}
@Override
public AsyncCallFuture<CommandResult> deleteTemplateAsync(
TemplateInfo template) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(
SnapshotInfo snapshot, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(
VolumeInfo volume, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,481 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.image;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.datastore.DataObjectManager;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.alert.AlertManager;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.dao.VMTemplateDao;
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.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.UriUtils;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.dao.UserVmDao;
@Component
public class TemplateServiceImpl implements TemplateService {
private static final Logger s_logger = Logger.getLogger(TemplateServiceImpl.class);
@Inject
ObjectInDataStoreManager _objectInDataStoreMgr;
@Inject
DataObjectManager _dataObjectMgr;
@Inject
DataStoreManager _storeMgr;
@Inject
ResourceLimitService _resourceLimitMgr;
@Inject
AccountManager _accountMgr;
@Inject
AlertManager _alertMgr;
@Inject
VMTemplateDao _templateDao;
@Inject
TemplateDataStoreDao _vmTemplateStoreDao;
@Inject
VolumeDataStoreDao _volumeStoreDao;
@Inject
DownloadMonitor _dlMonitor;
@Inject
AgentManager _agentMgr;
@Inject
SecondaryStorageVmManager _ssvmMgr;
@Inject
DataCenterDao _dcDao = null;
@Inject
VMTemplateZoneDao _vmTemplateZoneDao;
@Inject
ClusterDao _clusterDao;
@Inject
UserVmDao _userVmDao;
@Inject
VolumeDao _volumeDao;
class CreateTemplateContext<T> extends AsyncRpcConext<T> {
final TemplateInfo srcTemplate;
final DataStore store;
final AsyncCallFuture<CommandResult> future;
final DataObject templateOnStore;
public CreateTemplateContext(AsyncCompletionCallback<T> callback, TemplateInfo srcTemplate,
AsyncCallFuture<CommandResult> future,
DataStore store,
DataObject templateOnStore
) {
super(callback);
this.srcTemplate = srcTemplate;
this.future = future;
this.store = store;
this.templateOnStore = templateOnStore;
}
}
@Override
public AsyncCallFuture<CommandResult> createTemplateAsync(
TemplateInfo template, DataStore store) {
TemplateObject to = (TemplateObject) template;
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
// persist template_store_ref entry
DataObject templateOnStore = store.create(template);
// update template_store_ref state
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested);
CreateTemplateContext<CommandResult> context = new CreateTemplateContext<CommandResult>(null,
template,
future,
store,
templateOnStore
);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(templateOnStore, caller);
return future;
}
@Override
public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) {
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<DataStore> ssHosts = this._storeMgr.getImageStoresByScope(new ZoneScope(dcId));
if (ssHosts == null || ssHosts.isEmpty()){
return;
}
/*Download all the templates in zone with the same hypervisortype*/
for ( DataStore ssHost : ssHosts) {
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (rtngTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(rtngTmplt);
}
}
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (builtinTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(builtinTmplt);
}
}
for (VMTemplateVO template: toBeDownloaded) {
TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(ssHost.getId(), template.getId());
if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) {
_dlMonitor.downloadTemplateToStorage(template, ssHost, null);
}
}
}
}
@Override
public void handleTemplateSync(DataStore store) {
if (store == null) {
s_logger.warn("Huh? image store is null");
return;
}
long storeId = store.getId();
Long zoneId = store.getScope().getScopeId();
Map<String, TemplateProp> templateInfos = listTemplate(store);
if (templateInfos == null) {
return;
}
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<VMTemplateVO> allTemplates = null;
if (zoneId == null){
// region wide store
allTemplates = _templateDao.listAll();
}
else{
// zone wide store
allTemplates = _templateDao.listAllInZone(zoneId);
}
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
if (rtngTmplts != null) {
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (!allTemplates.contains(rtngTmplt)) {
allTemplates.add(rtngTmplt);
}
}
}
if (defaultBuiltin != null) {
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (!allTemplates.contains(builtinTmplt)) {
allTemplates.add(builtinTmplt);
}
}
}
toBeDownloaded.addAll(allTemplates);
for (VMTemplateVO tmplt : allTemplates) {
String uniqueName = tmplt.getUniqueName();
TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId());
if (templateInfos.containsKey(uniqueName)) {
TemplateProp tmpltInfo = templateInfos.remove(uniqueName);
toBeDownloaded.remove(tmplt);
if (tmpltStore != null) {
s_logger.info("Template Sync found " + uniqueName + " already in the template host table");
if (tmpltStore.getDownloadState() != Status.DOWNLOADED) {
tmpltStore.setErrorString("");
}
if (tmpltInfo.isCorrupted()) {
tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR);
String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId();
tmpltStore.setErrorString(msg);
s_logger.info("msg");
if (tmplt.getUrl() == null) {
msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId();
s_logger.warn(msg);
} else {
toBeDownloaded.add(tmplt);
}
} else {
tmpltStore.setDownloadPercent(100);
tmpltStore.setDownloadState(Status.DOWNLOADED);
tmpltStore.setInstallPath(tmpltInfo.getInstallPath());
tmpltStore.setSize(tmpltInfo.getSize());
tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize());
tmpltStore.setLastUpdated(new Date());
if (tmpltInfo.getSize() > 0) {
long accountId = tmplt.getAccountId();
try {
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl()));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId,
null, e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
}
_vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore);
} else {
tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl());
tmpltStore.setSize(tmpltInfo.getSize());
tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize());
_vmTemplateStoreDao.persist(tmpltStore);
this.associateTemplateToZone(tmplt.getId(), zoneId);
}
continue;
}
if (tmpltStore != null && tmpltStore.getDownloadState() != Status.DOWNLOADED) {
s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + storeId + ", will request download to start/resume shortly");
} else if (tmpltStore == null) {
s_logger.info("Template Sync did not find " + uniqueName + " on the server " + storeId + ", will request download shortly");
TemplateDataStoreVO templtStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl());
_vmTemplateStoreDao.persist(templtStore);
this.associateTemplateToZone(tmplt.getId(), zoneId);
}
}
if (toBeDownloaded.size() > 0) {
/* Only download templates whose hypervirsor type is in the zone */
List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId);
if (availHypers.isEmpty()) {
/*
* This is for cloudzone, local secondary storage resource
* started before cluster created
*/
availHypers.add(HypervisorType.KVM);
}
/* Baremetal need not to download any template */
availHypers.remove(HypervisorType.BareMetal);
availHypers.add(HypervisorType.None); // bug 9809: resume ISO
// download.
for (VMTemplateVO tmplt : toBeDownloaded) {
if (tmplt.getUrl() == null) { // If url is null we can't
// initiate the download
continue;
}
// check if there is a record for this template in this store
TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId());
// if this is private template, and there is no record for this
// template in this store, skip
if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) {
if (tmpltHost == null) {
continue;
}
}
if (availHypers.contains(tmplt.getHypervisorType())) {
if (tmpltHost != null ) {
continue;
}
s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + store.getName());
//TODO: we should pass a callback here
_dlMonitor.downloadTemplateToStorage(tmplt, store, null);
}
}
}
for (String uniqueName : templateInfos.keySet()) {
TemplateProp tInfo = templateInfos.get(uniqueName);
List<UserVmVO> userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId());
//check if there is any Vm using this ISO.
if (userVmUsingIso == null || userVmUsingIso.isEmpty()) {
DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(store.getUri(), tInfo.getInstallPath());
try {
HostVO ssAhost = _ssvmMgr.pickSsvmHost(store);
_agentMgr.sendToSecStorage(ssAhost, dtCommand, null);
} catch (AgentUnavailableException e) {
String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + storeId + " which isn't in the database";
s_logger.error(err);
return;
}
String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId + " since it isn't in the database";
s_logger.info(description);
}
}
}
// persist entry in template_zone_ref table. zoneId can be empty for region-wide image store, in that case,
// we will associate the template to all the zones.
private void associateTemplateToZone(long templateId, Long zoneId){
List<Long> dcs = new ArrayList<Long>();
if (zoneId != null ){
dcs.add(zoneId);
}
else{
List<DataCenterVO> zones = _dcDao.listAll();
for (DataCenterVO zone : zones){
dcs.add(zone.getId());
}
}
for (Long id : dcs) {
VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, templateId);
if (tmpltZoneVO == null) {
tmpltZoneVO = new VMTemplateZoneVO(id, templateId, new Date());
_vmTemplateZoneDao.persist(tmpltZoneVO);
} else {
tmpltZoneVO.setLastUpdated(new Date());
_vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO);
}
}
}
private Map<String, TemplateProp> listTemplate(DataStore ssHost) {
ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getUri());
HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssHost);
Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd);
if (answer != null && answer.getResult()) {
ListTemplateAnswer tanswer = (ListTemplateAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("can not list template for secondary storage host " + ssHost.getId());
}
}
return null;
}
protected Void createTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> callback,
CreateTemplateContext<CreateCmdResult> context) {
TemplateObject template = (TemplateObject)context.srcTemplate;
AsyncCallFuture<CommandResult> future = context.future;
CommandResult result = new CommandResult();
DataObject templateOnStore = context.templateOnStore;
CreateCmdResult callbackResult = callback.getResult();
if (callbackResult.isFailed()) {
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
template.stateTransit(TemplateEvent.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to update template state", e);
}
result.setResult(callbackResult.getResult());
future.complete(result);
return null;
}
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
template.stateTransit(TemplateEvent.OperationSucceeded);
} catch (NoTransitionException e) {
s_logger.debug("Failed to transit state", e);
result.setResult(e.toString());
future.complete(result);
return null;
}
future.complete(result);
return null;
}
@Override
public AsyncCallFuture<CommandResult> deleteTemplateAsync(
TemplateInfo template) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(
SnapshotInfo snapshot, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(
VolumeInfo volume, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -39,7 +39,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManag
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
@ -86,7 +86,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
//@Inject
//ImageDataStoreProviderManager imageProviderMgr;
@Inject
ImageService imageService;
TemplateService imageService;
@Inject
VolumeService volumeService;
@Inject

View File

@ -42,21 +42,16 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
private static final Logger s_logger = Logger.getLogger(SnapshotDataStoreDaoImpl.class);
private SearchBuilder<SnapshotDataStoreVO> updateStateSearch;
private SearchBuilder<SnapshotDataStoreVO> storeSearch;
private SearchBuilder<SnapshotDataStoreVO> liveStoreSearch;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
storeSearch = createSearchBuilder();
storeSearch = createSearchBuilder();
storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeSearch.done();
liveStoreSearch = createSearchBuilder();
liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
liveStoreSearch.done();
updateStateSearch = this.createSearchBuilder();
updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
@ -102,17 +97,11 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
return rows > 0;
}
@Override
public List<SnapshotDataStoreVO> listByStoreId(long id) {
SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();
sc.setParameters("store_id", id);
return listIncludingRemovedBy(sc);
}
@Override
public List<SnapshotDataStoreVO> listLiveByStoreId(long id) {
SearchCriteria<SnapshotDataStoreVO> sc = liveStoreSearch.create();
sc.setParameters("store_id", id);
sc.setParameters("destroyed", false);
return listIncludingRemovedBy(sc);
}

View File

@ -30,6 +30,7 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@ -42,23 +43,20 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
private static final Logger s_logger = Logger.getLogger(TemplateDataStoreDaoImpl.class);
private SearchBuilder<TemplateDataStoreVO> updateStateSearch;
private SearchBuilder<TemplateDataStoreVO> storeSearch;
private SearchBuilder<TemplateDataStoreVO> liveStoreSearch;
private SearchBuilder<TemplateDataStoreVO> storeTemplateStateSearch;
private SearchBuilder<TemplateDataStoreVO> storeTemplateDownloadStatusSearch;
private SearchBuilder<TemplateDataStoreVO> storeTemplateSearch;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
storeSearch = createSearchBuilder();
storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeSearch.done();
liveStoreSearch = createSearchBuilder();
liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
liveStoreSearch.done();
updateStateSearch = this.createSearchBuilder();
updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
@ -72,6 +70,14 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
storeTemplateStateSearch.and("destroyed", storeTemplateStateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeTemplateStateSearch.done();
storeTemplateDownloadStatusSearch = createSearchBuilder();
storeTemplateDownloadStatusSearch.and("template_id", storeTemplateDownloadStatusSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
storeTemplateDownloadStatusSearch.and("store_id", storeTemplateDownloadStatusSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeTemplateDownloadStatusSearch.and("downloadState", storeTemplateDownloadStatusSearch.entity().getDownloadState(), SearchCriteria.Op.IN);
storeTemplateDownloadStatusSearch.and("destroyed", storeTemplateDownloadStatusSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeTemplateDownloadStatusSearch.done();
storeTemplateSearch = createSearchBuilder();
storeTemplateSearch.and("store_id", storeTemplateSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeTemplateSearch.and("template_id", storeTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
@ -118,16 +124,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
return rows > 0;
}
@Override
public List<TemplateDataStoreVO> listByStoreId(long id) {
SearchCriteria<TemplateDataStoreVO> sc = storeSearch.create();
sc.setParameters("store_id", id);
return listIncludingRemovedBy(sc);
}
@Override
public List<TemplateDataStoreVO> listLiveByStoreId(long id) {
SearchCriteria<TemplateDataStoreVO> sc = liveStoreSearch.create();
sc.setParameters("store_id", id);
sc.setParameters("destroyed", false);
return listIncludingRemovedBy(sc);
}
@ -152,6 +153,17 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
return search(sc, null);
}
@Override
public List<TemplateDataStoreVO> listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status) {
SearchCriteria<TemplateDataStoreVO> sc = storeTemplateStateSearch.create();
sc.setParameters("template_id", templateId);
sc.setParameters("store_id", storeId);
sc.setParameters("downloadState", (Object[])status);
return search(sc, null);
}
@Override
public TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId) {
SearchCriteria<TemplateDataStoreVO> sc = storeTemplateSearch.create();

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.storage.VolumeHostVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@ -42,21 +43,30 @@ import com.cloud.utils.db.UpdateBuilder;
public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Long> implements VolumeDataStoreDao {
private static final Logger s_logger = Logger.getLogger(VolumeDataStoreDaoImpl.class);
private SearchBuilder<VolumeDataStoreVO> updateStateSearch;
private SearchBuilder<VolumeDataStoreVO> volumeSearch;
private SearchBuilder<VolumeDataStoreVO> storeSearch;
private SearchBuilder<VolumeDataStoreVO> liveStoreSearch;
private SearchBuilder<VolumeDataStoreVO> storeVolumeSearch;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
storeSearch = createSearchBuilder();
storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeSearch.done();
liveStoreSearch = createSearchBuilder();
liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
liveStoreSearch.done();
volumeSearch = createSearchBuilder();
volumeSearch.and("volume_id", volumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
volumeSearch.and("destroyed", volumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
volumeSearch.done();
storeVolumeSearch = createSearchBuilder();
storeVolumeSearch.and("store_id", storeVolumeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeVolumeSearch.and("volume_id", storeVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
storeVolumeSearch.and("destroyed", storeVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
storeVolumeSearch.done();
updateStateSearch = this.createSearchBuilder();
updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
@ -102,16 +112,11 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
return rows > 0;
}
@Override
public List<VolumeDataStoreVO> listByStoreId(long id) {
SearchCriteria<VolumeDataStoreVO> sc = storeSearch.create();
sc.setParameters("store_id", id);
return listIncludingRemovedBy(sc);
}
@Override
public List<VolumeDataStoreVO> listLiveByStoreId(long id) {
SearchCriteria<VolumeDataStoreVO> sc = liveStoreSearch.create();
sc.setParameters("store_id", id);
sc.setParameters("destroyed", false);
return listIncludingRemovedBy(sc);
}
@ -125,4 +130,23 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
remove(sc);
txn.commit();
}
@Override
public VolumeDataStoreVO findByVolumeId(long volumeId) {
SearchCriteria<VolumeDataStoreVO> sc = volumeSearch.create();
sc.setParameters("volume_id", volumeId);
sc.setParameters("destroyed", false);
return findOneBy(sc);
}
@Override
public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId) {
SearchCriteria<VolumeDataStoreVO> sc = storeVolumeSearch.create();
sc.setParameters("store_id", storeId);
sc.setParameters("volume_id", volumeId);
sc.setParameters("destroyed", false);
return findOneBy(sc);
}
}

View File

@ -318,6 +318,10 @@ public class VolumeObject implements VolumeInfo {
return this.payload;
}
public VolumeVO getVolume(){
return this.volumeVO;
}
@Override
public HypervisorType getHypervisorType() {
return this.volumeDao.getHypervisorType(this.volumeVO.getId());

View File

@ -18,6 +18,11 @@
*/
package org.apache.cloudstack.storage.volume;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
@ -41,19 +46,37 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.template.TemplateProp;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.UriUtils;
import com.cloud.utils.db.DB;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
@ -77,13 +100,29 @@ public class VolumeServiceImpl implements VolumeService {
@Inject
VolumeDataFactory volFactory;
@Inject SnapshotManager snapshotMgr;
@Inject
ResourceLimitService _resourceLimitMgr;
@Inject
DownloadMonitor _dlMonitor;
@Inject
AccountManager _accountMgr;
@Inject
AlertManager _alertMgr;
@Inject VMInstanceDao vmDao;
@Inject
ConfigurationDao configDao;
@Inject
SecondaryStorageVmManager _ssvmMgr;
@Inject
AgentManager _agentMgr;
@Inject
VolumeDataStoreDao _volumeStoreDao;
@Inject
VolumeDao _volumeDao;
public VolumeServiceImpl() {
}
private class CreateVolumeContext<T> extends AsyncRpcConext<T> {
private DataObject volume;
@ -96,17 +135,17 @@ public class VolumeServiceImpl implements VolumeService {
this.volume = volume;
this.future = future;
}
public DataObject getVolume() {
return this.volume;
}
public AsyncCallFuture<VolumeApiResult> getFuture() {
return this.future;
}
}
@Override
public AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, DataStore dataStore) {
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
@ -117,11 +156,11 @@ public class VolumeServiceImpl implements VolumeService {
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createVolumeCallback(null, null))
.setContext(context);
dataStore.getDriver().createAsync(volumeOnStore, caller);
return future;
}
protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
CreateCmdResult result = callback.getResult();
DataObject vo = context.getVolume();
@ -139,7 +178,7 @@ public class VolumeServiceImpl implements VolumeService {
context.getFuture().complete(volResult);
return null;
}
private class DeleteVolumeContext<T> extends AsyncRpcConext<T> {
private final VolumeObject volume;
private AsyncCallFuture<VolumeApiResult> future;
@ -151,11 +190,11 @@ public class VolumeServiceImpl implements VolumeService {
this.volume = volume;
this.future = future;
}
public VolumeObject getVolume() {
return this.volume;
}
public AsyncCallFuture<VolumeApiResult> getFuture() {
return this.future;
}
@ -171,7 +210,7 @@ public class VolumeServiceImpl implements VolumeService {
future.complete(result);
return future;
}
String vmName = null;
VolumeVO vol = this.volDao.findById(volume.getId());
if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) {
@ -194,19 +233,19 @@ public class VolumeServiceImpl implements VolumeService {
return future;
}
VolumeObject vo = (VolumeObject)volume;
volume.processEvent(Event.ExpungeRequested);
DeleteVolumeContext<VolumeApiResult> context = new DeleteVolumeContext<VolumeApiResult>(null, vo, future);
AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null))
.setContext(context);
volume.getDataStore().getDriver().deleteAsync(volume, caller);
return future;
}
public Void deleteVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> callback, DeleteVolumeContext<VolumeApiResult> context) {
CommandResult result = callback.getResult();
VolumeObject vo = context.getVolume();
@ -249,7 +288,7 @@ public class VolumeServiceImpl implements VolumeService {
private final TemplateInfo srcTemplate;
private final AsyncCallFuture<VolumeApiResult> future;
final DataObject destObj;
public CreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volume, PrimaryDataStore datastore,
public CreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volume, PrimaryDataStore datastore,
TemplateInfo srcTemplate,
AsyncCallFuture<VolumeApiResult> future, DataObject destObj) {
super(callback);
@ -259,11 +298,11 @@ public class VolumeServiceImpl implements VolumeService {
this.srcTemplate = srcTemplate;
this.destObj = destObj;
}
public VolumeInfo getVolume() {
return this.volume;
}
public PrimaryDataStore getDataStore() {
return this.dataStore;
}
@ -271,13 +310,13 @@ public class VolumeServiceImpl implements VolumeService {
public TemplateInfo getSrcTemplate() {
return this.srcTemplate;
}
public AsyncCallFuture<VolumeApiResult> getFuture() {
return this.future;
}
}
static class CreateBaseImageResult extends CommandResult {
final TemplateInfo template;
public CreateBaseImageResult(TemplateInfo template) {
@ -285,7 +324,7 @@ public class VolumeServiceImpl implements VolumeService {
this.template = template;
}
}
private TemplateInfo waitForTemplateDownloaded(PrimaryDataStore store, TemplateInfo template) {
int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
int sleepTime = 120;
@ -306,16 +345,16 @@ public class VolumeServiceImpl implements VolumeService {
}
@DB
protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) {
DataObject templateOnPrimaryStoreObj = dataStore.create(template);
CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume,
CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume,
dataStore,
template,
future, templateOnPrimaryStoreObj);
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null))
.setContext(context);
try {
templateOnPrimaryStoreObj.processEvent(Event.CreateOnlyRequested);
} catch (Exception e) {
@ -330,7 +369,7 @@ public class VolumeServiceImpl implements VolumeService {
}
}
}
try {
motionSrv.copyAsync(template, templateOnPrimaryStoreObj, caller);
} catch (Exception e) {
@ -342,12 +381,12 @@ public class VolumeServiceImpl implements VolumeService {
}
return;
}
@DB
protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
CopyCommandResult result = callback.getResult();
VolumeApiResult res = new VolumeApiResult(context.getVolume());
AsyncCallFuture<VolumeApiResult> future = context.getFuture();
DataObject templateOnPrimaryStoreObj = context.destObj;
if (!result.isSuccess()) {
@ -356,18 +395,18 @@ public class VolumeServiceImpl implements VolumeService {
future.complete(res);
return null;
}
templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed);
createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future);
return null;
}
private class CreateVolumeFromBaseImageContext<T> extends AsyncRpcConext<T> {
private final VolumeObject vo;
private final AsyncCallFuture<VolumeApiResult> future;
private final DataStore primaryStore;
private final DataObject templateOnStore;
public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo,
public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo,
DataStore primaryStore,
DataObject templateOnStore,
AsyncCallFuture<VolumeApiResult> future) {
@ -377,13 +416,13 @@ public class VolumeServiceImpl implements VolumeService {
this.primaryStore = primaryStore;
this.templateOnStore = templateOnStore;
}
public AsyncCallFuture<VolumeApiResult> getFuture() {
return this.future;
}
}
@DB
protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) {
VolumeObject vo = (VolumeObject)volume;
@ -398,23 +437,23 @@ public class VolumeServiceImpl implements VolumeService {
motionSrv.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller);
return;
}
@DB
public Void copyBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
VolumeObject vo = context.vo;
CopyCommandResult result = callback.getResult();
VolumeApiResult volResult = new VolumeApiResult(vo);
if (result.isSuccess()) {
if (result.getPath() != null) {
vo.setPath(result.getPath());
}
vo.processEvent(Event.OperationSuccessed);
vo.processEvent(Event.OperationSuccessed);
} else {
vo.processEvent(Event.OperationFailed);
volResult.setResult(result.getResult());
}
AsyncCallFuture<VolumeApiResult> future = context.getFuture();
future.complete(volResult);
return null;
@ -427,12 +466,12 @@ public class VolumeServiceImpl implements VolumeService {
TemplateInfo templateOnPrimaryStore = pd.getTemplate(template.getId());
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
VolumeApiResult result = new VolumeApiResult(volume);
if (templateOnPrimaryStore == null) {
createBaseImageAsync(volume, pd, template, future);
return future;
}
createVolumeFromBaseImageAsync(volume, templateOnPrimaryStore, pd, future);
return future;
}
@ -441,13 +480,13 @@ public class VolumeServiceImpl implements VolumeService {
@DB
public boolean destroyVolume(long volumeId)
throws ConcurrentOperationException {
VolumeInfo vol = this.volFactory.getVolume(volumeId);
vol.processEvent(Event.DestroyRequested);
this.snapshotMgr.deletePoliciesForVolume(volumeId);
vol.processEvent(Event.OperationSuccessed);
return true;
}
@ -455,11 +494,11 @@ public class VolumeServiceImpl implements VolumeService {
public AsyncCallFuture<VolumeApiResult> createVolumeFromSnapshot(
VolumeInfo volume, DataStore store, SnapshotInfo snapshot) {
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
try {
DataObject volumeOnStore = store.create(volume);
volume.processEvent(Event.CreateOnlyRequested);
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null,
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null,
(VolumeObject)volume, store, volumeOnStore, future);
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null))
@ -471,11 +510,11 @@ public class VolumeServiceImpl implements VolumeService {
result.setResult(e.toString());
future.complete(result);
}
return future;
}
protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
CopyCommandResult result = callback.getResult();
VolumeInfo volume = context.vo;
@ -487,19 +526,19 @@ public class VolumeServiceImpl implements VolumeService {
} else {
event = Event.OperationSuccessed;
}
try {
volume.processEvent(event);
} catch (Exception e) {
s_logger.debug("create volume from snapshot failed", e);
apiResult.setResult(e.toString());
}
AsyncCallFuture<VolumeApiResult> future = context.future;
future.complete(apiResult);
return null;
}
protected VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePool pool) {
Long lastPoolId = volume.getPoolId();
VolumeVO newVol = new VolumeVO(volume);
@ -511,7 +550,7 @@ public class VolumeServiceImpl implements VolumeService {
newVol.setPodId(pool.getPodId());
return this.volDao.persist(newVol);
}
private class CopyVolumeContext<T> extends AsyncRpcConext<T> {
final VolumeInfo srcVolume;
@ -529,7 +568,7 @@ public class VolumeServiceImpl implements VolumeService {
this.destStore = destStore;
this.future = future;
}
}
@Override
public AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume,
@ -540,7 +579,7 @@ public class VolumeServiceImpl implements VolumeService {
if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) {
s_logger.debug(
"There are snapshots creating on this volume, can not move this volume");
res.setResult("There are snapshots creating on this volume, can not move this volume");
future.complete(res);
return future;
@ -551,7 +590,7 @@ public class VolumeServiceImpl implements VolumeService {
destVolume.processEvent(Event.CreateOnlyRequested);
srcVolume.processEvent(Event.CopyingRequested);
CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume,
CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume,
destVolume,
destStore);
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
@ -565,7 +604,7 @@ public class VolumeServiceImpl implements VolumeService {
}
return future;
}
protected Void copyVolumeCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
VolumeInfo srcVolume = context.srcVolume;
VolumeInfo destVolume = context.destVolume;
@ -593,13 +632,13 @@ public class VolumeServiceImpl implements VolumeService {
res.setResult(e.toString());
future.complete(res);
}
return null;
}
@Override
public AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store) {
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
VolumeObject vo = (VolumeObject) volume;
@ -607,11 +646,11 @@ public class VolumeServiceImpl implements VolumeService {
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().registerVolumeCallback(null, null))
.setContext(context);
dataObjectMgr.createAsync(volume, store, caller, true);
return future;
}
protected Void registerVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
CreateCmdResult result = callback.getResult();
VolumeObject vo = (VolumeObject)context.volume;
@ -624,7 +663,7 @@ public class VolumeServiceImpl implements VolumeService {
context.future.complete(res);
return null;
}
@Override
public AsyncCallFuture<VolumeApiResult> resize(VolumeInfo volume) {
@ -645,12 +684,12 @@ public class VolumeServiceImpl implements VolumeService {
volume.getDataStore().getDriver().resize(volume, caller);
return future;
}
protected Void resizeVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
CreateCmdResult result = callback.getResult();
AsyncCallFuture<VolumeApiResult> future = context.future;
VolumeInfo volume = (VolumeInfo)context.volume;
if (result.isFailed()) {
try {
volume.processEvent(Event.OperationFailed);
@ -662,7 +701,7 @@ public class VolumeServiceImpl implements VolumeService {
future.complete(res);
return null;
}
try {
volume.processEvent(Event.OperationSuccessed);
} catch(Exception e) {
@ -672,13 +711,137 @@ public class VolumeServiceImpl implements VolumeService {
future.complete(res);
return null;
}
VolumeApiResult res = new VolumeApiResult(volume);
future.complete(res);
return null;
}
@Override
public void handleVolumeSync(DataStore store) {
if (store == null) {
s_logger.warn("Huh? ssHost is null");
return;
}
long storeId = store.getId();
Long zoneId = store.getScope().getScopeId();
Map<Long, TemplateProp> volumeInfos = listVolume(store);
if (volumeInfos == null) {
return;
}
List<VolumeDataStoreVO> dbVolumes = _volumeStoreDao.listByStoreId(storeId);
List<VolumeDataStoreVO> toBeDownloaded = new ArrayList<VolumeDataStoreVO>(dbVolumes);
for (VolumeDataStoreVO volumeStore : dbVolumes){
VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId());
//Exists then don't download
if (volumeInfos.containsKey(volume.getId())){
TemplateProp volInfo = volumeInfos.remove(volume.getId());
toBeDownloaded.remove(volumeStore);
s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table");
if (volumeStore.getDownloadState() != Status.DOWNLOADED) {
volumeStore.setErrorString("");
}
if (volInfo.isCorrupted()) {
volumeStore.setDownloadState(Status.DOWNLOAD_ERROR);
String msg = "Volume " + volume.getUuid() + " is corrupted on image store ";
volumeStore.setErrorString(msg);
s_logger.info("msg");
if (volumeStore.getDownloadUrl() == null) {
msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in image store: " + volumeStore.getDataStoreId();
s_logger.warn(msg);
} else {
toBeDownloaded.add(volumeStore);
}
} else { // Put them in right status
volumeStore.setDownloadPercent(100);
volumeStore.setDownloadState(Status.DOWNLOADED);
volumeStore.setInstallPath(volInfo.getInstallPath());
volumeStore.setSize(volInfo.getSize());
volumeStore.setPhysicalSize(volInfo.getPhysicalSize());
volumeStore.setLastUpdated(new Date());
_volumeStoreDao.update(volumeStore.getId(), volumeStore);
if (volume.getSize() == 0) {
// Set volume size in volumes table
volume.setSize(volInfo.getSize());
_volumeDao.update(volumeStore.getVolumeId(), volume);
}
if (volInfo.getSize() > 0) {
try {
String url = _volumeStoreDao.findByVolumeId(volume.getId()).getDownloadUrl();
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
volInfo.getSize() - UriUtils.getRemoteSize(url));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(),
volume.getPodId(), e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
}
continue;
}
// Volume is not on secondary but we should download.
if (volumeStore.getDownloadState() != Status.DOWNLOADED) {
s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId + ", will request download to start/resume shortly");
toBeDownloaded.add(volumeStore);
}
}
//Download volumes which haven't been downloaded yet.
if (toBeDownloaded.size() > 0) {
for (VolumeDataStoreVO volumeHost : toBeDownloaded) {
if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download
continue;
}
s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + store.getName());
//TODO: pass a callback later
_dlMonitor.downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), store, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat(), null);
}
}
//Delete volumes which are not present on DB.
for (Long uniqueName : volumeInfos.keySet()) {
TemplateProp vInfo = volumeInfos.get(uniqueName);
DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(store.getUri(), vInfo.getInstallPath());
try {
HostVO ssAhost = _ssvmMgr.pickSsvmHost(store);
_agentMgr.sendToSecStorage(ssAhost, dtCommand, null);
} catch (AgentUnavailableException e) {
String err = "Failed to delete " + vInfo.getTemplateName() + " on image store " + storeId + " which isn't in the database";
s_logger.error(err);
return;
}
String description = "Deleted volume " + vInfo.getTemplateName() + " on image store " + storeId + " since it isn't in the database";
s_logger.info(description);
}
}
private Map<Long, TemplateProp> listVolume(DataStore store) {
ListVolumeCommand cmd = new ListVolumeCommand(store.getUri());
HostVO ssAhost = _ssvmMgr.pickSsvmHost(store);
Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd);
if (answer != null && answer.getResult()) {
ListVolumeAnswer tanswer = (ListVolumeAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Can not list volumes for image store " + store.getId());
}
}
return null;
}
}

View File

@ -215,7 +215,7 @@ import com.cloud.storage.Volume;
import com.cloud.storage.template.Processor;
import com.cloud.storage.template.Processor.FormatInfo;
import com.cloud.storage.template.QCOW2Processor;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.TemplateLocation;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@ -2381,7 +2381,7 @@ ServerResource {
return new Answer(cmd, false, " Failed to create storage pool");
}
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
storagepool.getCapacity(), storagepool.getUsed(), tInfo);

View File

@ -114,7 +114,7 @@ import com.cloud.resource.hypervisor.HypervisorResource;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
@ -458,7 +458,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
setupHeartBeat(pool.getUuid());
OvmStoragePool.Details d = OvmStoragePool.getDetailsByUuid(_conn, pool.getUuid());
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, d.totalSpace, d.freeSpace, tInfo);
return answer;
} catch (Exception e) {

View File

@ -74,7 +74,7 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@ -357,7 +357,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa
txn = Transaction.open(Transaction.CLOUD_DB);
txn.close();
}
return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap<String, TemplateInfo>());
return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap<String, TemplateProp>());
}
@Override
@ -398,7 +398,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa
txn = Transaction.open(Transaction.CLOUD_DB);
txn.close();
}
return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap<String, TemplateInfo>());
return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap<String, TemplateProp>());
}
@Override
@ -449,9 +449,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa
List<MockVolumeVO> volumes = _mockVolumeDao.findByStorageIdAndType(storage.getId(),
MockVolumeType.VOLUME);
Map<Long, TemplateInfo> templateInfos = new HashMap<Long, TemplateInfo>();
Map<Long, TemplateProp> templateInfos = new HashMap<Long, TemplateProp>();
for (MockVolumeVO volume : volumes) {
templateInfos.put(volume.getId(), new TemplateInfo(volume.getName(), volume.getPath()
templateInfos.put(volume.getId(), new TemplateProp(volume.getName(), volume.getPath()
.replaceAll(storage.getMountPoint(), ""), volume.getSize(), volume.getSize(), true, false));
}
txn.commit();
@ -492,9 +492,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa
List<MockVolumeVO> templates = _mockVolumeDao.findByStorageIdAndType(storage.getId(),
MockVolumeType.TEMPLATE);
Map<String, TemplateInfo> templateInfos = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> templateInfos = new HashMap<String, TemplateProp>();
for (MockVolumeVO template : templates) {
templateInfos.put(template.getName(), new TemplateInfo(template.getName(), template.getPath()
templateInfos.put(template.getName(), new TemplateProp(template.getName(), template.getPath()
.replaceAll(storage.getMountPoint(), ""), template.getSize(), template.getSize(), true, false));
}
txn.commit();

View File

@ -51,7 +51,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Networks.RouterPrivateIpStrategy;
import com.cloud.simulator.MockVMVO;
import com.cloud.storage.Storage.StorageResourceType;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine.State;
@ -168,7 +168,7 @@ public class AgentRoutingResource extends AgentStorageResource {
}
private StartupStorageCommand initializeLocalSR() {
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
StoragePoolInfo poolInfo = _simMgr.getLocalStorage(hostGuid);

View File

@ -210,7 +210,7 @@ import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.storage.resource.StoragePoolResource;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
@ -3137,7 +3137,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
DatastoreSummary summary = new DatastoreMO(getServiceContext(), morDatastore).getSummary();
long capacity = summary.getCapacity();
long available = summary.getFreeSpace();
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo);
return answer;
} catch (Throwable e) {

View File

@ -233,7 +233,7 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@ -5287,7 +5287,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
s_logger.warn(msg);
return new Answer(cmd, false, msg);
}
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo);
return answer;
} catch (XenAPIException e) {

View File

@ -25,6 +25,16 @@
<artifactId>cloud-engine-storage-image</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-volume</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-snapshot</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>

View File

@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -118,11 +119,10 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
TemplateObject tData = (TemplateObject)data;
_downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback);
} else if (data.getType() == DataObjectType.VOLUME) {
VolumeVO vol = this.volumeDao.findById(data.getId());
VolumeInfo volInfo = (VolumeInfo)data;
VolumeObject volInfo = (VolumeObject)data;
RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload();
_downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()));
_downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback);
}
CreateCmdResult result = new CreateCmdResult(null, null);

View File

@ -32,6 +32,16 @@
<artifactId>cloud-engine-storage-image</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-volume</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-snapshot</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>

View File

@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -118,11 +119,10 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver {
TemplateObject tData = (TemplateObject)data;
_downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback);
} else if (data.getType() == DataObjectType.VOLUME) {
VolumeVO vol = this.volumeDao.findById(data.getId());
VolumeInfo volInfo = (VolumeInfo)data;
VolumeObject volInfo = (VolumeObject)data;
RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload();
_downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()));
_downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback);
}
CreateCmdResult result = new CreateCmdResult(null, null);

View File

@ -25,6 +25,16 @@
<artifactId>cloud-engine-storage-image</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-volume</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-snapshot</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>

View File

@ -25,6 +25,16 @@
<artifactId>cloud-engine-storage-image</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-volume</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine-storage-snapshot</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>

View File

@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.cloudstack.storage.image.store.TemplateObject;
import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -118,11 +119,10 @@ public class SwiftImageStoreDriverImpl implements ImageStoreDriver {
TemplateObject tData = (TemplateObject)data;
_downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback);
} else if (data.getType() == DataObjectType.VOLUME) {
VolumeVO vol = this.volumeDao.findById(data.getId());
VolumeInfo volInfo = (VolumeInfo)data;
VolumeObject volInfo = (VolumeObject)data;
RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload();
_downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()));
_downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(),
payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback);
}
CreateCmdResult result = new CreateCmdResult(null, null);

View File

@ -1993,15 +1993,15 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
_accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId());
// Verify that there are no live snapshot, template, volume on the image store to be deleted
List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listLiveByStoreId(storeId);
List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId);
if ( snapshots != null && snapshots.size() > 0 ){
throw new CloudRuntimeException("Cannot delete image store with active snapshots backup!");
}
List<VolumeDataStoreVO> volumes = _volumeStoreDao.listLiveByStoreId(storeId);
List<VolumeDataStoreVO> volumes = _volumeStoreDao.listByStoreId(storeId);
if ( volumes != null && volumes.size() > 0 ){
throw new CloudRuntimeException("Cannot delete image store with active volumes backup!");
}
List<TemplateDataStoreVO> templates = _templateStoreDao.listLiveByStoreId(storeId);
List<TemplateDataStoreVO> templates = _templateStoreDao.listByStoreId(storeId);
if ( templates != null && templates.size() > 0 ){
throw new CloudRuntimeException("Cannot delete image store with active templates backup!");
}

View File

@ -18,6 +18,7 @@ package com.cloud.storage.download;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@ -26,9 +27,15 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
@ -52,6 +59,8 @@ import com.cloud.exception.ConnectionException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.VMTemplateHostVO;
@ -117,57 +126,68 @@ public class DownloadListener implements Listener {
public static final String DOWNLOAD_ABANDONED=Status.ABANDONED.toString();
private HostVO sserver;
private HostVO ssAgent;
private HostVO _sserver;
private HostVO _ssAgent;
private VMTemplateVO template;
private VolumeVO volume;
private boolean downloadActive = true;
private VMTemplateVO _template;
private VolumeVO _volume;
private boolean _downloadActive = true;
private VolumeHostDao volumeHostDao;
private VolumeHostDao _volumeHostDao;
private VolumeDataStoreDao _volumeStoreDao;
private VolumeDao _volumeDao;
private StorageManager _storageMgr;
private VMTemplateHostDao vmTemplateHostDao;
private VMTemplateHostDao _vmTemplateHostDao;
private TemplateDataStoreDao _vmTemplateStoreDao;
private VMTemplateDao _vmTemplateDao;
private ResourceLimitService _resourceLimitMgr;
private AccountManager _accountMgr;
private AlertManager _alertMgr;
private final DownloadMonitorImpl downloadMonitor;
private final DownloadMonitorImpl _downloadMonitor;
private DownloadState currState;
private DownloadState _currState;
private DownloadCommand cmd;
private DownloadCommand _cmd;
private Timer timer;
private Timer _timer;
private StatusTask statusTask;
private TimeoutTask timeoutTask;
private Date lastUpdated = new Date();
private String jobId;
private StatusTask _statusTask;
private TimeoutTask _timeoutTask;
private Date _lastUpdated = new Date();
private String _jobId;
private final Map<String, DownloadState> stateMap = new HashMap<String, DownloadState>();
private Long templateHostId;
private Long volumeHostId;
private final Map<String, DownloadState> _stateMap = new HashMap<String, DownloadState>();
private Long _templateHostId;
private Long _volumeHostId;
private DataStore sstore;
private Long templateStoreId;
private AsyncCompletionCallback<CreateCmdResult> callback;
private DataStore _sstore;
private Long _templateStoreId;
private Long _volumeStoreId;
private AsyncCompletionCallback<CreateCmdResult> _callback;
@Inject
private ResourceManager _resourceMgr;
@Inject
private TemplateService _imageSrv;
@Inject
private DataStoreManager _storeMgr;
@Inject
private VolumeService _volumeSrv;
public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) {
this.ssAgent = ssAgent;
this.sserver = host;
this.template = template;
this.vmTemplateHostDao = dao;
this.downloadMonitor = downloadMonitor;
this.cmd = cmd;
this.templateHostId = templHostId;
this._ssAgent = ssAgent;
this._sserver = host;
this._template = template;
this._vmTemplateHostDao = dao;
this._downloadMonitor = downloadMonitor;
this._cmd = cmd;
this._templateHostId = templHostId;
initStateMachine();
this.currState=getState(Status.NOT_DOWNLOADED.toString());
this.timer = _timer;
this.timeoutTask = new TimeoutTask(this);
this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
this._currState=getState(Status.NOT_DOWNLOADED.toString());
this._timer = _timer;
this._timeoutTask = new TimeoutTask(this);
this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL);
this._vmTemplateDao = templateDao;
this._resourceLimitMgr = _resourceLimitMgr;
this._accountMgr = _accountMgr;
@ -177,63 +197,64 @@ public class DownloadListener implements Listener {
// TODO: this constructor should be the one used for template only, remove other template constructor later
public DownloadListener(HostVO ssAgent, DataStore store, VMTemplateVO template, Timer _timer, TemplateDataStoreDao dao, Long templStoreId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr, AsyncCompletionCallback<CreateCmdResult> callback) {
this.ssAgent = ssAgent;
this.sstore = store;
this.template = template;
this._ssAgent = ssAgent;
this._sstore = store;
this._template = template;
this._vmTemplateStoreDao = dao;
this.downloadMonitor = downloadMonitor;
this.cmd = cmd;
this.templateStoreId = templStoreId;
this._downloadMonitor = downloadMonitor;
this._cmd = cmd;
this._templateStoreId = templStoreId;
initStateMachine();
this.currState=getState(Status.NOT_DOWNLOADED.toString());
this.timer = _timer;
this.timeoutTask = new TimeoutTask(this);
this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
this._currState=getState(Status.NOT_DOWNLOADED.toString());
this._timer = _timer;
this._timeoutTask = new TimeoutTask(this);
this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL);
this._vmTemplateDao = templateDao;
this._resourceLimitMgr = _resourceLimitMgr;
this._accountMgr = _accountMgr;
this._alertMgr = _alertMgr;
this.callback = callback;
this._callback = callback;
updateDatabase(Status.NOT_DOWNLOADED, "");
}
public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) {
this.ssAgent = ssAgent;
this.sserver = host;
this.volume = volume;
this.volumeHostDao = dao;
this.downloadMonitor = downloadMonitor;
this.cmd = cmd;
this.volumeHostId = volHostId;
public DownloadListener(HostVO ssAgent, DataStore store, VolumeVO volume, Timer _timer, VolumeDataStoreDao dao, Long volStoreId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr, AsyncCompletionCallback<CreateCmdResult> callback) {
this._ssAgent = ssAgent;
this._sstore = store;
this._volume = volume;
this._volumeStoreDao = dao;
this._downloadMonitor = downloadMonitor;
this._cmd = cmd;
this._volumeStoreId = volStoreId;
initStateMachine();
this.currState=getState(Status.NOT_DOWNLOADED.toString());
this.timer = _timer;
this.timeoutTask = new TimeoutTask(this);
this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
this._currState=getState(Status.NOT_DOWNLOADED.toString());
this._timer = _timer;
this._timeoutTask = new TimeoutTask(this);
this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL);
this._volumeDao = volumeDao;
this._storageMgr = storageMgr;
this._resourceLimitMgr = _resourceLimitMgr;
this._accountMgr = _accountMgr;
this._alertMgr = _alertMgr;
this._callback = callback;
updateDatabase(Status.NOT_DOWNLOADED, "");
}
public void setCurrState(VMTemplateHostVO.Status currState) {
this.currState = getState(currState.toString());
this._currState = getState(currState.toString());
}
private void initStateMachine() {
stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this));
stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this));
stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this));
stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this));
stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this));
_stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this));
_stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this));
_stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this));
_stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this));
_stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this));
}
private DownloadState getState(String stateName) {
return stateMap.get(stateName);
return _stateMap.get(stateName);
}
public void sendCommand(RequestType reqType) {
@ -243,10 +264,10 @@ public class DownloadListener implements Listener {
}
try {
DownloadProgressCommand dcmd = new DownloadProgressCommand(getCommand(), getJobId(), reqType);
if (template == null){
if (_template == null){
dcmd.setResourceType(ResourceType.VOLUME);
}
downloadMonitor.send(ssAgent.getId(), dcmd, this);
_downloadMonitor.send(_ssAgent.getId(), dcmd, this);
} catch (AgentUnavailableException e) {
s_logger.debug("Send command failed", e);
setDisconnected();
@ -264,63 +285,63 @@ public class DownloadListener implements Listener {
}
public void logDisconnect() {
if (template != null){
s_logger.warn("Unable to monitor download progress of " + template.getName() + " at host " + sserver.getName());
if (_template != null){
s_logger.warn("Unable to monitor download progress of " + _template.getName() + " at host " + _sserver.getName());
}else {
s_logger.warn("Unable to monitor download progress of " + volume.getName() + " at host " + sserver.getName());
s_logger.warn("Unable to monitor download progress of " + _volume.getName() + " at host " + _sserver.getName());
}
}
public synchronized void updateDatabase(Status state, String errorString) {
if (template != null){
VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate();
if (_template != null){
VMTemplateHostVO vo = _vmTemplateHostDao.createForUpdate();
vo.setDownloadState(state);
vo.setLastUpdated(new Date());
vo.setErrorString(errorString);
vmTemplateHostDao.update(getTemplateHostId(), vo);
_vmTemplateHostDao.update(getTemplateHostId(), vo);
}else {
VolumeHostVO vo = volumeHostDao.createForUpdate();
VolumeHostVO vo = _volumeHostDao.createForUpdate();
vo.setDownloadState(state);
vo.setLastUpdated(new Date());
vo.setErrorString(errorString);
volumeHostDao.update(getVolumeHostId(), vo);
_volumeHostDao.update(getVolumeHostId(), vo);
}
}
public void log(String message, Level level) {
if (template != null){
s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName());
if (_template != null){
s_logger.log(level, message + ", template=" + _template.getName() + " at host " + _sserver.getName());
}else {
s_logger.log(level, message + ", volume=" + volume.getName() + " at host " + sserver.getName());
s_logger.log(level, message + ", volume=" + _volume.getName() + " at host " + _sserver.getName());
}
}
private Long getTemplateHostId() {
if (templateHostId == null){
VMTemplateHostVO templHost = vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId());
templateHostId = templHost.getId();
if (_templateHostId == null){
VMTemplateHostVO templHost = _vmTemplateHostDao.findByHostTemplate(_sserver.getId(), _template.getId());
_templateHostId = templHost.getId();
}
return templateHostId;
return _templateHostId;
}
private Long getTemplateStoreId() {
if (templateStoreId == null){
TemplateDataStoreVO templStore = _vmTemplateStoreDao.findByStoreTemplate(sstore.getId(), template.getId());
templateStoreId = templStore.getId();
if (_templateStoreId == null){
TemplateDataStoreVO templStore = _vmTemplateStoreDao.findByStoreTemplate(_sstore.getId(), _template.getId());
_templateStoreId = templStore.getId();
}
return templateStoreId;
return _templateStoreId;
}
private Long getVolumeHostId() {
if (volumeHostId == null){
VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
volumeHostId = volHost.getId();
if (_volumeHostId == null){
VolumeHostVO volHost = _volumeHostDao.findByHostVolume(_sserver.getId(), _volume.getId());
_volumeHostId = volHost.getId();
}
return volumeHostId;
return _volumeHostId;
}
public DownloadListener(DownloadMonitorImpl monitor) {
downloadMonitor = monitor;
_downloadMonitor = monitor;
}
@ -350,15 +371,15 @@ public class DownloadListener implements Listener {
}
private synchronized void transition(DownloadEvent event, Object evtObj) {
if (currState == null) {
if (_currState == null) {
return;
}
String prevName = currState.getName();
String nextState = currState.handleEvent(event, evtObj);
String prevName = _currState.getName();
String nextState = _currState.handleEvent(event, evtObj);
if (nextState != null) {
currState = getState(nextState);
if (currState != null) {
currState.onEntry(prevName, event, evtObj);
_currState = getState(nextState);
if (_currState != null) {
_currState.onEntry(prevName, event, evtObj);
} else {
throw new CloudRuntimeException("Invalid next state: currState="+prevName+", evt="+event + ", next=" + nextState);
}
@ -368,7 +389,7 @@ public class DownloadListener implements Listener {
}
public synchronized void updateDatabase(DownloadAnswer answer) {
if (template != null){
if (_template != null){
TemplateDataStoreVO updateBuilder = _vmTemplateStoreDao.createForUpdate();
updateBuilder.setDownloadPercent(answer.getDownloadPct());
updateBuilder.setDownloadState(answer.getDownloadStatus());
@ -380,40 +401,58 @@ public class DownloadListener implements Listener {
updateBuilder.setSize(answer.getTemplateSize());
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
// only invoke callback when Download is completed or errored so that callback will update template_store_ref state column
Status dndStatus = answer.getDownloadStatus();
// if (dndStatus == Status.DOWNLOAD_ERROR || dndStatus == Status.DOWNLOADED ){
if ( _callback != null ){
if (dndStatus == Status.DOWNLOAD_ERROR){
CreateCmdResult result = new CreateCmdResult(null, null);
result.setSucess(false);
result.setResult("Download template failed");
_callback.complete(result);
} else if (dndStatus == Status.DOWNLOADED){
CreateCmdResult result = new CreateCmdResult(null, null);
_callback.complete(result);
}
}
else{
// no callback specified, just update state here
if (dndStatus == Status.DOWNLOAD_ERROR){
updateBuilder.setState(ObjectInDataStoreStateMachine.State.Failed);
} else if (dndStatus == Status.DOWNLOAD_IN_PROGRESS){
updateBuilder.setState(ObjectInDataStoreStateMachine.State.Creating2);
} else if (dndStatus == Status.DOWNLOADED){
updateBuilder.setState(ObjectInDataStoreStateMachine.State.Ready);
}
}
// }
_vmTemplateStoreDao.update(getTemplateStoreId(), updateBuilder);
if (answer.getCheckSum() != null) {
VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
templateDaoBuilder.setChecksum(answer.getCheckSum());
_vmTemplateDao.update(template.getId(), templateDaoBuilder);
_vmTemplateDao.update(_template.getId(), templateDaoBuilder);
}
if (answer.getTemplateSize() > 0) {
//long hostId = vmTemplateHostDao.findByTemplateId(template.getId()).getHostId();
long accountId = template.getAccountId();
long accountId = _template.getAccountId();
try {
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
answer.getTemplateSize() - UriUtils.getRemoteSize(template.getUrl()));
answer.getTemplateSize() - UriUtils.getRemoteSize(_template.getUrl()));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, sserver.getDataCenterId(),
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, _sserver.getDataCenterId(),
null, e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
// only invoke callback when Download is completed or errored so that callback will update template_store_ref state column
Status dndStatus = answer.getDownloadStatus();
if (dndStatus == Status.DOWNLOAD_ERROR || dndStatus == Status.DOWNLOADED ){
if ( callback != null ){
CreateCmdResult result = new CreateCmdResult(null, null);
callback.complete(result);
}
}
} else {
VolumeHostVO updateBuilder = volumeHostDao.createForUpdate();
VolumeHostVO updateBuilder = _volumeHostDao.createForUpdate();
updateBuilder.setDownloadPercent(answer.getDownloadPct());
updateBuilder.setDownloadState(answer.getDownloadStatus());
updateBuilder.setLastUpdated(new Date());
@ -424,25 +463,25 @@ public class DownloadListener implements Listener {
updateBuilder.setSize(answer.getTemplateSize());
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
volumeHostDao.update(getVolumeHostId(), updateBuilder);
_volumeHostDao.update(getVolumeHostId(), updateBuilder);
// Update volume size in Volume table.
VolumeVO updateVolume = _volumeDao.createForUpdate();
updateVolume.setSize(answer.getTemplateSize());
_volumeDao.update(volume.getId(), updateVolume);
_volumeDao.update(_volume.getId(), updateVolume);
if (answer.getTemplateSize() > 0) {
try {
String url = volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl();
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
String url = _volumeHostDao.findByVolumeId(_volume.getId()).getDownloadUrl();
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(_volume.getAccountId()),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
answer.getTemplateSize() - UriUtils.getRemoteSize(url));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(),
volume.getPodId(), e.getMessage(), e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, _volume.getDataCenterId(),
_volume.getPodId(), e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
_resourceLimitMgr.recalculateResourceCount(_volume.getAccountId(), _volume.getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
@ -474,8 +513,12 @@ public class DownloadListener implements Listener {
@Override
public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
if (cmd instanceof StartupRoutingCommand) {
downloadMonitor.handleSysTemplateDownload(agent);
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(agent.getId(), agent.getDataCenterId());
HypervisorType hostHyper = agent.getHypervisorType();
if (hypers.contains(hostHyper)) {
return;
}
_imageSrv.handleSysTemplateDownload(hostHyper, agent.getDataCenterId());
}
/* This can be removed since
else if ( cmd instanceof StartupStorageCommand) {
@ -488,16 +531,20 @@ public class DownloadListener implements Listener {
}
}*/
else if ( cmd instanceof StartupSecondaryStorageCommand ) {
downloadMonitor.handleSync(agent.getDataCenterId());
List<DataStore> imageStores = this._storeMgr.getImageStoresByScope(new ZoneScope(agent.getDataCenterId()));
for (DataStore store : imageStores){
_volumeSrv.handleVolumeSync(store);
_imageSrv.handleTemplateSync(store);
}
}
}
public void setCommand(DownloadCommand _cmd) {
this.cmd = _cmd;
this._cmd = _cmd;
}
public DownloadCommand getCommand() {
return cmd;
return _cmd;
}
@ -506,63 +553,63 @@ public class DownloadListener implements Listener {
}
public void setJobId(String _jobId) {
this.jobId = _jobId;
this._jobId = _jobId;
}
public String getJobId() {
return jobId;
return _jobId;
}
public void scheduleStatusCheck(RequestType request) {
if (statusTask != null) statusTask.cancel();
if (_statusTask != null) _statusTask.cancel();
statusTask = new StatusTask(this, request);
timer.schedule(statusTask, STATUS_POLL_INTERVAL);
_statusTask = new StatusTask(this, request);
_timer.schedule(_statusTask, STATUS_POLL_INTERVAL);
}
public void scheduleTimeoutTask(long delay) {
if (timeoutTask != null) timeoutTask.cancel();
if (_timeoutTask != null) _timeoutTask.cancel();
timeoutTask = new TimeoutTask(this);
timer.schedule(timeoutTask, delay);
_timeoutTask = new TimeoutTask(this);
_timer.schedule(_timeoutTask, delay);
if (s_logger.isDebugEnabled()) {
log("Scheduling timeout at " + delay + " ms", Level.DEBUG);
}
}
public void scheduleImmediateStatusCheck(RequestType request) {
if (statusTask != null) statusTask.cancel();
statusTask = new StatusTask(this, request);
timer.schedule(statusTask, SMALL_DELAY);
if (_statusTask != null) _statusTask.cancel();
_statusTask = new StatusTask(this, request);
_timer.schedule(_statusTask, SMALL_DELAY);
}
public boolean isDownloadActive() {
return downloadActive;
return _downloadActive;
}
public void cancelStatusTask() {
if (statusTask != null) statusTask.cancel();
if (_statusTask != null) _statusTask.cancel();
}
public Date getLastUpdated() {
return lastUpdated;
return _lastUpdated;
}
public void setLastUpdated() {
lastUpdated = new Date();
_lastUpdated = new Date();
}
public void setDownloadInactive(Status reason) {
downloadActive=false;
if (template != null){
downloadMonitor.handleDownloadEvent(sserver, template, reason);
_downloadActive=false;
if (_template != null){
_downloadMonitor.handleDownloadEvent(_sserver, _template, reason);
}else {
downloadMonitor.handleDownloadEvent(sserver, volume, reason);
_downloadMonitor.handleDownloadEvent(_sserver, _volume, reason);
}
}
public void cancelTimeoutTask() {
if (timeoutTask != null) timeoutTask.cancel();
if (_timeoutTask != null) _timeoutTask.cancel();
}
public void logDownloadStart() {

View File

@ -16,8 +16,6 @@
// under the License.
package com.cloud.storage.download;
import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@ -28,7 +26,6 @@ import com.cloud.host.HostVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.utils.component.Manager;
/**
@ -37,23 +34,17 @@ import com.cloud.utils.component.Manager;
*/
public interface DownloadMonitor extends Manager{
public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback<CreateCmdResult> callback);
public void downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback<CreateCmdResult> callback);
public void cancelAllDownloads(Long templateId);
public void handleTemplateSync(DataStore store);
public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer)
throws StorageUnavailableException;
void handleSysTemplateDownload(HostVO hostId);
//void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateProp> templateInfos);
void handleSync(Long dcId);
//public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format);
void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos);
boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format);
void handleVolumeSync(HostVO ssHost);
public void downloadVolumeToStorage(VolumeVO volume, DataStore store, String url, String checkSum, ImageFormat format, AsyncCompletionCallback<CreateCmdResult> callback);
}

View File

@ -18,12 +18,9 @@ package com.cloud.storage.download;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
@ -33,19 +30,17 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
@ -53,16 +48,10 @@ import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
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.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.event.EventTypes;
@ -70,9 +59,7 @@ import com.cloud.event.UsageEventUtils;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -80,12 +67,10 @@ import com.cloud.resource.ResourceManager;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.SwiftVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VolumeHostVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.StoragePoolHostDao;
@ -101,12 +86,10 @@ import com.cloud.storage.dao.VolumeHostDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.storage.template.TemplateConstants;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.UriUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.JoinBuilder;
@ -117,14 +100,10 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import edu.emory.mathcs.backport.java.util.Collections;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@ -152,6 +131,8 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
@Inject
VolumeHostDao _volumeHostDao;
@Inject
VolumeDataStoreDao _volumeStoreDao;
@Inject
AlertManager _alertMgr;
@Inject
protected SwiftManager _swiftMgr;
@ -206,6 +187,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
final Map<TemplateDataStoreVO, DownloadListener> _listenerTemplateMap = new ConcurrentHashMap<TemplateDataStoreVO, DownloadListener>();
final Map<VMTemplateHostVO, DownloadListener> _listenerMap = new ConcurrentHashMap<VMTemplateHostVO, DownloadListener>();
final Map<VolumeHostVO, DownloadListener> _listenerVolumeMap = new ConcurrentHashMap<VolumeHostVO, DownloadListener>();
final Map<VolumeDataStoreVO, DownloadListener> _listenerVolMap = new ConcurrentHashMap<VolumeDataStoreVO, DownloadListener>();
public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException {
@ -256,7 +238,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
public boolean isTemplateUpdateable(Long templateId, Long storeId) {
List<TemplateDataStoreVO> downloadsInProgress =
_vmTemplateStoreDao.listByTemplateStoreStatus(templateId, storeId, ObjectInDataStoreStateMachine.State.Creating, ObjectInDataStoreStateMachine.State.Creating2, ObjectInDataStoreStateMachine.State.Ready);
_vmTemplateStoreDao.listByTemplateStoreDownloadStatus(templateId, storeId, Status.DOWNLOAD_IN_PROGRESS, Status.DOWNLOADED );
return (downloadsInProgress.size() == 0);
}
@ -370,7 +352,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
TemplateDataStoreVO vmTemplateStore = null;
vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId());
// we should already persist one entry in template_store_ref table, so vmTemplateStore should not be null
if (vmTemplateStore == null) {
// This method can be invoked other places, for example, handleTemplateSync, in that case, vmTemplateStore may be null
vmTemplateStore = new TemplateDataStoreVO(store.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUrl());
_vmTemplateStoreDao.persist(vmTemplateStore);
} else
if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) {
downloadJobExists = true;
}
@ -420,42 +406,33 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
@Override
public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback<CreateCmdResult> callback) {
public void downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback<CreateCmdResult> callback) {
long templateId = template.getId();
if (isTemplateUpdateable(templateId, store.getId())) {
if ( template != null && template.getUrl() != null ){
initiateTemplateDownload(template, store, callback);
}
}
return true;
}
@Override
public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format) {
List<HostVO> ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(zoneId);
Collections.shuffle(ssHosts);
HostVO ssHost = ssHosts.get(0);
downloadVolumeToStorage(volume, ssHost, url, checkSum, format);
return true;
}
private void downloadVolumeToStorage(VolumeVO volume, HostVO sserver, String url, String checkSum, ImageFormat format) {
public void downloadVolumeToStorage(VolumeVO volume, DataStore store, String url, String checkSum, ImageFormat format, AsyncCompletionCallback<CreateCmdResult> callback) {
boolean downloadJobExists = false;
VolumeHostVO volumeHost = null;
VolumeDataStoreVO volumeHost = null;
volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
volumeHost = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId());
if (volumeHost == null) {
volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), sserver.getDataCenterId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null,
volumeHost = new VolumeDataStoreVO(store.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null,
"jobid0000", null, url, checkSum, format);
_volumeHostDao.persist(volumeHost);
_volumeStoreDao.persist(volumeHost);
} else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) {
downloadJobExists = true;
}
Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes();
String secUrl = sserver.getStorageUrl();
String secUrl = store.getUri();
if(volumeHost != null) {
start();
DownloadCommand dcmd = new DownloadCommand(secUrl, volume, maxVolumeSizeInBytes, checkSum, url, format);
@ -465,45 +442,35 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
dcmd.setResourceType(ResourceType.VOLUME);
}
HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver);
if( ssvm == null ) {
s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName());
HostVO ssAhost = _ssvmMgr.pickSsvmHost(store);
if( ssAhost == null ) {
s_logger.warn("There is no secondary storage VM for image store " + store.getName());
return;
}
DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(),
this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr);
DownloadListener dl = new DownloadListener(ssAhost, store, volume, _timer, _volumeStoreDao, volumeHost.getId(),
this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr, callback);
if (downloadJobExists) {
dl.setCurrState(volumeHost.getDownloadState());
}
DownloadListener old = null;
synchronized (_listenerVolumeMap) {
old = _listenerVolumeMap.put(volumeHost, dl);
synchronized (_listenerVolMap) {
old = _listenerVolMap.put(volumeHost, dl);
}
if( old != null ) {
old.abandon();
}
try {
send(ssvm.getId(), dcmd, dl);
send(ssAhost.getId(), dcmd, dl);
} catch (AgentUnavailableException e) {
s_logger.warn("Unable to start /resume download of volume " + volume.getName() + " to " + sserver.getName(), e);
s_logger.warn("Unable to start /resume download of volume " + volume.getName() + " to " + store.getName(), e);
dl.setDisconnected();
dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
}
}
}
/*
private void initiateTemplateDownload(Long templateId, DataStore store) {
VMTemplateVO template = _templateDao.findById(templateId);
if (template != null && (template.getUrl() != null)) {
//find all storage hosts and tell them to initiate download
downloadTemplateToStorage(template, store);
}
}
*/
@DB
public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) {
@ -583,62 +550,18 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
txn.commit();
}
@Override
public void handleSysTemplateDownload(HostVO host) {
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId());
HypervisorType hostHyper = host.getHypervisorType();
if (hypers.contains(hostHyper)) {
return;
}
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<DataStore> ssHosts = this.storeMgr.getImageStoresByScope(new ZoneScope(host.getDataCenterId()));
if (ssHosts == null || ssHosts.isEmpty()){
return;
}
/*
List<HostVO> ssHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.SecondaryStorage, host.getDataCenterId());
if (ssHosts == null || ssHosts.isEmpty()) {
return;
}
*/
/*Download all the templates in zone with the same hypervisortype*/
for ( DataStore ssHost : ssHosts) {
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (rtngTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(rtngTmplt);
}
}
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (builtinTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(builtinTmplt);
}
}
for (VMTemplateVO template: toBeDownloaded) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), template.getId());
if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) {
//TODO: pass callback here
initiateTemplateDownload(template, ssHost, null);
}
}
}
}
/*
@Override
public void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos){
public void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateProp> templateInfos){
if ( templateInfos == null ) {
return;
}
Long hostId = host.getId();
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
for ( VMTemplateVO tmplt : rtngTmplts ) {
TemplateInfo tmpltInfo = templateInfos.get(tmplt.getUniqueName());
TemplateProp tmpltInfo = templateInfos.get(tmplt.getUniqueName());
if ( tmpltInfo == null ) {
continue;
}
@ -651,354 +574,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
}
}
}
*/
@Override
public void handleSync(Long dcId) {
if (dcId != null) {
List<HostVO> ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId);
for (HostVO ssHost : ssHosts) {
//handleTemplateSync(ssHost);
handleVolumeSync(ssHost);
}
}
List<DataStore> imageStores = this.storeMgr.getImageStoresByScope(new ZoneScope(dcId));
for (DataStore store : imageStores){
handleTemplateSync(store);
}
}
private Map<String, TemplateInfo> listTemplate(DataStore ssHost) {
ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getUri());
HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssHost);
Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd);
if (answer != null && answer.getResult()) {
ListTemplateAnswer tanswer = (ListTemplateAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("can not list template for secondary storage host " + ssHost.getId());
}
}
return null;
}
private Map<Long, TemplateInfo> listVolume(HostVO ssHost) {
ListVolumeCommand cmd = new ListVolumeCommand(ssHost.getStorageUrl());
Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd);
if (answer != null && answer.getResult()) {
ListVolumeAnswer tanswer = (ListVolumeAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Can not list volumes for secondary storage host " + ssHost.getId());
}
}
return null;
}
private Map<String, TemplateInfo> listTemplate(SwiftVO swift) {
if (swift == null) {
return null;
}
ListTemplateCommand cmd = new ListTemplateCommand(swift.toSwiftTO());
Answer answer = _agentMgr.sendToSSVM(null, cmd);
if (answer != null && answer.getResult()) {
ListTemplateAnswer tanswer = (ListTemplateAnswer) answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("can not list template for swift " + swift);
}
}
return null;
}
@Override
public void handleVolumeSync(HostVO ssHost) {
if (ssHost == null) {
s_logger.warn("Huh? ssHost is null");
return;
}
long sserverId = ssHost.getId();
if (!(ssHost.getType() == Host.Type.SecondaryStorage || ssHost.getType() == Host.Type.LocalSecondaryStorage)) {
s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host");
return;
}
Map<Long, TemplateInfo> volumeInfos = listVolume(ssHost);
if (volumeInfos == null) {
return;
}
List<VolumeHostVO> dbVolumes = _volumeHostDao.listBySecStorage(sserverId);
List<VolumeHostVO> toBeDownloaded = new ArrayList<VolumeHostVO>(dbVolumes);
for (VolumeHostVO volumeHost : dbVolumes){
VolumeVO volume = _volumeDao.findById(volumeHost.getVolumeId());
//Exists then don't download
if (volumeInfos.containsKey(volume.getId())){
TemplateInfo volInfo = volumeInfos.remove(volume.getId());
toBeDownloaded.remove(volumeHost);
s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume host table");
if (volumeHost.getDownloadState() != Status.DOWNLOADED) {
volumeHost.setErrorString("");
}
if (volInfo.isCorrupted()) {
volumeHost.setDownloadState(Status.DOWNLOAD_ERROR);
String msg = "Volume " + volume.getUuid() + " is corrupted on secondary storage ";
volumeHost.setErrorString(msg);
s_logger.info("msg");
if (volumeHost.getDownloadUrl() == null) {
msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + volumeHost.getHostId();
s_logger.warn(msg);
} else {
toBeDownloaded.add(volumeHost);
}
} else { // Put them in right status
volumeHost.setDownloadPercent(100);
volumeHost.setDownloadState(Status.DOWNLOADED);
volumeHost.setInstallPath(volInfo.getInstallPath());
volumeHost.setSize(volInfo.getSize());
volumeHost.setPhysicalSize(volInfo.getPhysicalSize());
volumeHost.setLastUpdated(new Date());
_volumeHostDao.update(volumeHost.getId(), volumeHost);
if (volume.getSize() == 0) {
// Set volume size in volumes table
volume.setSize(volInfo.getSize());
_volumeDao.update(volumeHost.getVolumeId(), volume);
}
if (volInfo.getSize() > 0) {
try {
String url = _volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl();
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
volInfo.getSize() - UriUtils.getRemoteSize(url));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(),
volume.getPodId(), e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
}
continue;
}
// Volume is not on secondary but we should download.
if (volumeHost.getDownloadState() != Status.DOWNLOADED) {
s_logger.info("Volume Sync did not find " + volume.getName() + " ready on server " + sserverId + ", will request download to start/resume shortly");
toBeDownloaded.add(volumeHost);
}
}
//Download volumes which haven't been downloaded yet.
if (toBeDownloaded.size() > 0) {
for (VolumeHostVO volumeHost : toBeDownloaded) {
if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download
continue;
}
s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + ssHost.getName());
downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), ssHost, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat());
}
}
//Delete volumes which are not present on DB.
for (Long uniqueName : volumeInfos.keySet()) {
TemplateInfo vInfo = volumeInfos.get(uniqueName);
DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), vInfo.getInstallPath());
try {
_agentMgr.sendToSecStorage(ssHost, dtCommand, null);
} catch (AgentUnavailableException e) {
String err = "Failed to delete " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database";
s_logger.error(err);
return;
}
String description = "Deleted volume " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database";
s_logger.info(description);
}
}
@Override
public void handleTemplateSync(DataStore ssStore) {
if (ssStore == null) {
s_logger.warn("Huh? image store is null");
return;
}
long storeId = ssStore.getId();
Long zoneId = ssStore.getScope().getScopeId();
Map<String, TemplateInfo> templateInfos = listTemplate(ssStore);
if (templateInfos == null) {
return;
}
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<VMTemplateVO> allTemplates = null;
if (zoneId == null){
// region wide store
allTemplates = _templateDao.listAll();
}
else{
// zone wide store
allTemplates = _templateDao.listAllInZone(zoneId);
}
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
if (rtngTmplts != null) {
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (!allTemplates.contains(rtngTmplt)) {
allTemplates.add(rtngTmplt);
}
}
}
if (defaultBuiltin != null) {
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (!allTemplates.contains(builtinTmplt)) {
allTemplates.add(builtinTmplt);
}
}
}
toBeDownloaded.addAll(allTemplates);
for (VMTemplateVO tmplt : allTemplates) {
String uniqueName = tmplt.getUniqueName();
TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId());
if (templateInfos.containsKey(uniqueName)) {
TemplateInfo tmpltInfo = templateInfos.remove(uniqueName);
toBeDownloaded.remove(tmplt);
if (tmpltStore != null) {
s_logger.info("Template Sync found " + uniqueName + " already in the template host table");
if (tmpltStore.getDownloadState() != Status.DOWNLOADED) {
tmpltStore.setErrorString("");
}
if (tmpltInfo.isCorrupted()) {
tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR);
String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId();
tmpltStore.setErrorString(msg);
s_logger.info("msg");
if (tmplt.getUrl() == null) {
msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId();
s_logger.warn(msg);
} else {
toBeDownloaded.add(tmplt);
}
} else {
tmpltStore.setDownloadPercent(100);
tmpltStore.setDownloadState(Status.DOWNLOADED);
tmpltStore.setInstallPath(tmpltInfo.getInstallPath());
tmpltStore.setSize(tmpltInfo.getSize());
tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize());
tmpltStore.setLastUpdated(new Date());
if (tmpltInfo.getSize() > 0) {
long accountId = tmplt.getAccountId();
try {
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId),
com.cloud.configuration.Resource.ResourceType.secondary_storage,
tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl()));
} catch (ResourceAllocationException e) {
s_logger.warn(e.getMessage());
_alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId,
null, e.getMessage(), e.getMessage());
} finally {
_resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(),
com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
}
}
}
_vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore);
} else {
tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl());
tmpltStore.setSize(tmpltInfo.getSize());
tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize());
_vmTemplateStoreDao.persist(tmpltStore);
this.associateTemplateToZone(tmplt.getId(), zoneId);
}
continue;
}
if (tmpltStore != null && tmpltStore.getDownloadState() != Status.DOWNLOADED) {
s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + storeId + ", will request download to start/resume shortly");
} else if (tmpltStore == null) {
s_logger.info("Template Sync did not find " + uniqueName + " on the server " + storeId + ", will request download shortly");
TemplateDataStoreVO templtStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl());
_vmTemplateStoreDao.persist(templtStore);
this.associateTemplateToZone(tmplt.getId(), zoneId);
}
}
if (toBeDownloaded.size() > 0) {
/* Only download templates whose hypervirsor type is in the zone */
List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId);
if (availHypers.isEmpty()) {
/*
* This is for cloudzone, local secondary storage resource
* started before cluster created
*/
availHypers.add(HypervisorType.KVM);
}
/* Baremetal need not to download any template */
availHypers.remove(HypervisorType.BareMetal);
availHypers.add(HypervisorType.None); // bug 9809: resume ISO
// download.
for (VMTemplateVO tmplt : toBeDownloaded) {
if (tmplt.getUrl() == null) { // If url is null we can't
// initiate the download
continue;
}
// if this is private template, and there is no record for this
// template in this sHost, skip
if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(storeId, tmplt.getId());
if (tmpltHost == null) {
continue;
}
}
if (availHypers.contains(tmplt.getHypervisorType())) {
if (_swiftMgr.isSwiftEnabled()) {
if (_swiftMgr.isTemplateInstalled(tmplt.getId())) {
continue;
}
}
s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssStore.getName());
//TODO: we should pass a callback here
initiateTemplateDownload(tmplt, ssStore, null);
}
}
}
for (String uniqueName : templateInfos.keySet()) {
TemplateInfo tInfo = templateInfos.get(uniqueName);
List<UserVmVO> userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId());
//check if there is any Vm using this ISO.
if (userVmUsingIso == null || userVmUsingIso.isEmpty()) {
DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssStore.getUri(), tInfo.getInstallPath());
try {
HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssStore);
_agentMgr.sendToSecStorage(ssAhost, dtCommand, null);
} catch (AgentUnavailableException e) {
String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + storeId + " which isn't in the database";
s_logger.error(err);
return;
}
String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId + " since it isn't in the database";
s_logger.info(description);
}
}
}
@Override
public void cancelAllDownloads(Long templateId) {
@ -1067,30 +645,6 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
}
}
// persist entry in template_zone_ref table. zoneId can be empty for region-wide image store, in that case,
// we will associate the template to all the zones.
private void associateTemplateToZone(long templateId, Long zoneId){
List<Long> dcs = new ArrayList<Long>();
if (zoneId != null ){
dcs.add(zoneId);
}
else{
List<DataCenterVO> zones = _dcDao.listAll();
for (DataCenterVO zone : zones){
dcs.add(zone.getId());
}
}
for (Long id : dcs) {
VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, templateId);
if (tmpltZoneVO == null) {
tmpltZoneVO = new VMTemplateZoneVO(id, templateId, new Date());
_vmTemplateZoneDao.persist(tmpltZoneVO);
} else {
tmpltZoneVO.setLastUpdated(new Date());
_vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO);
}
}
}
}

View File

@ -50,7 +50,7 @@ import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.template.TemplateConstants;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateProp;
public class DummySecondaryStorageResource extends ServerResourceBase implements ServerResource {
@ -113,7 +113,7 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements
public StartupCommand[] initialize() {
final StartupStorageCommand cmd = new StartupStorageCommand("dummy",
StoragePoolType.NetworkFilesystem, 1024*1024*1024*100L,
new HashMap<String, TemplateInfo>());
new HashMap<String, TemplateProp>());
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
cmd.setIqn(null);
@ -173,12 +173,12 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements
return _useServiceVm;
}
public Map<String, TemplateInfo> getDefaultSystemVmTemplateInfo() {
public Map<String, TemplateProp> getDefaultSystemVmTemplateInfo() {
List<VMTemplateVO> tmplts = _tmpltDao.listAllSystemVMTemplates();
Map<String, TemplateInfo> tmpltInfo = new HashMap<String, TemplateInfo>();
Map<String, TemplateProp> tmpltInfo = new HashMap<String, TemplateProp>();
if (tmplts != null) {
for (VMTemplateVO tmplt : tmplts) {
TemplateInfo routingInfo = new TemplateInfo(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false);
TemplateProp routingInfo = new TemplateProp(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false);
tmpltInfo.put(tmplt.getUniqueName(), routingInfo);
}
}

View File

@ -36,7 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.log4j.Logger;
@ -75,7 +75,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
@Inject AgentManager _agentMgr;
@Inject DataStoreManager storeMgr;
@Inject ImageService imageService;
@Inject TemplateService imageService;
@Inject ImageDataFactory imageFactory;
@Inject TemplateManager templateMgr;

View File

@ -35,7 +35,7 @@ import com.cloud.utils.Pair;
/**
* TemplateManager manages the templates stored on secondary storage. It is responsible for creating private/public templates.
*/
public interface TemplateManager extends TemplateService{
public interface TemplateManager extends TemplateApiService{
/**
* Prepares a template for vm creation for a certain storage pool.

View File

@ -58,7 +58,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
@ -187,8 +187,8 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Component
@Local(value={TemplateManager.class, TemplateService.class})
public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateService {
@Local(value={TemplateManager.class, TemplateApiService.class})
public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateApiService {
private final static Logger s_logger = Logger.getLogger(TemplateManagerImpl.class);
@Inject VMTemplateDao _tmpltDao;
@Inject VMTemplateHostDao _tmpltHostDao;
@ -246,7 +246,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Inject
SnapshotDataFactory snapshotFactory;
@Inject
ImageService imageSvr;
TemplateService imageSvr;
@Inject
DataStoreManager dataStoreMgr;
@Inject