mirror of https://github.com/apache/cloudstack.git
Remove ImagetransferProgress Command
This commit is contained in:
parent
07bca60fc4
commit
c40b30bc4a
|
|
@ -62,10 +62,6 @@ public class ImageTransferResponse extends BaseResponse {
|
|||
@Param(description = "the image transfer direction: upload / download")
|
||||
private String direction;
|
||||
|
||||
@SerializedName("progress")
|
||||
@Param(description = "progress in percentage for the upload image transfer")
|
||||
private Integer progress;
|
||||
|
||||
@SerializedName(ApiConstants.CREATED)
|
||||
@Param(description = "the date created")
|
||||
private Date created;
|
||||
|
|
@ -102,10 +98,6 @@ public class ImageTransferResponse extends BaseResponse {
|
|||
this.direction = direction;
|
||||
}
|
||||
|
||||
public void setProgress(Integer progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,6 @@ import com.cloud.utils.component.PluggableService;
|
|||
*/
|
||||
public interface KVMBackupExportService extends Configurable, PluggableService {
|
||||
|
||||
ConfigKey<Long> ImageTransferPollingInterval = new ConfigKey<>("Advanced", Long.class,
|
||||
"image.transfer.polling.interval",
|
||||
"10",
|
||||
"The image transfer progress polling interval in seconds.", true, ConfigKey.Scope.Global);
|
||||
|
||||
ConfigKey<Integer> ImageTransferIdleTimeoutSeconds = new ConfigKey<>("Advanced", Integer.class,
|
||||
"image.transfer.idle.timeout.seconds",
|
||||
"600",
|
||||
|
|
|
|||
|
|
@ -1,47 +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
|
||||
//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.backup;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
||||
public class GetImageTransferProgressAnswer extends Answer {
|
||||
private Map<String, Long> progressMap; // transferId -> progress percentage (0-100)
|
||||
|
||||
public GetImageTransferProgressAnswer() {
|
||||
}
|
||||
|
||||
public GetImageTransferProgressAnswer(GetImageTransferProgressCommand cmd, boolean success, String details) {
|
||||
super(cmd, success, details);
|
||||
}
|
||||
|
||||
public GetImageTransferProgressAnswer(GetImageTransferProgressCommand cmd, boolean success, String details,
|
||||
Map<String, Long> progressMap) {
|
||||
super(cmd, success, details);
|
||||
this.progressMap = progressMap;
|
||||
}
|
||||
|
||||
public Map<String, Long> getProgressMap() {
|
||||
return progressMap;
|
||||
}
|
||||
|
||||
public void setProgressMap(Map<String, Long> progressMap) {
|
||||
this.progressMap = progressMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +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
|
||||
//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.backup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class GetImageTransferProgressCommand extends Command {
|
||||
private List<String> transferIds;
|
||||
private Map<String, String> volumePaths; // transferId -> volume path
|
||||
private Map<String, Long> volumeSizes; // transferId -> volume size
|
||||
|
||||
public GetImageTransferProgressCommand() {
|
||||
}
|
||||
|
||||
public GetImageTransferProgressCommand(List<String> transferIds, Map<String, String> volumePaths, Map<String, Long> volumeSizes) {
|
||||
this.transferIds = transferIds;
|
||||
this.volumePaths = volumePaths;
|
||||
this.volumeSizes = volumeSizes;
|
||||
}
|
||||
|
||||
public List<String> getTransferIds() {
|
||||
return transferIds;
|
||||
}
|
||||
|
||||
public void setTransferIds(List<String> transferIds) {
|
||||
this.transferIds = transferIds;
|
||||
}
|
||||
|
||||
public Map<String, String> getVolumePaths() {
|
||||
return volumePaths;
|
||||
}
|
||||
|
||||
public void setVolumePaths(Map<String, String> volumePaths) {
|
||||
this.volumePaths = volumePaths;
|
||||
}
|
||||
|
||||
public Map<String, Long> getVolumeSizes() {
|
||||
return volumeSizes;
|
||||
}
|
||||
|
||||
public void setVolumeSizes(Map<String, Long> volumeSizes) {
|
||||
this.volumeSizes = volumeSizes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -75,9 +75,6 @@ public class ImageTransferVO implements ImageTransfer {
|
|||
@Column(name = "signed_ticket_id")
|
||||
private String signedTicketId;
|
||||
|
||||
@Column(name = "progress")
|
||||
private Integer progress;
|
||||
|
||||
@Column(name = "account_id")
|
||||
Long accountId;
|
||||
|
||||
|
|
@ -210,15 +207,6 @@ public class ImageTransferVO implements ImageTransfer {
|
|||
this.signedTicketId = signedTicketId;
|
||||
}
|
||||
|
||||
public Integer getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(Integer progress) {
|
||||
this.progress = progress;
|
||||
this.updated = new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return ImageTransfer.class;
|
||||
|
|
|
|||
|
|
@ -1,95 +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
|
||||
//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 com.cloud.hypervisor.kvm.resource.wrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.backup.GetImageTransferProgressAnswer;
|
||||
import org.apache.cloudstack.backup.GetImageTransferProgressCommand;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||
import com.cloud.resource.CommandWrapper;
|
||||
import com.cloud.resource.ResourceWrapper;
|
||||
|
||||
@ResourceWrapper(handles = GetImageTransferProgressCommand.class)
|
||||
public class LibvirtGetImageTransferProgressCommandWrapper extends CommandWrapper<GetImageTransferProgressCommand, Answer, LibvirtComputingResource> {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public Answer execute(GetImageTransferProgressCommand cmd, LibvirtComputingResource resource) {
|
||||
try {
|
||||
List<String> transferIds = cmd.getTransferIds();
|
||||
Map<String, String> volumePaths = cmd.getVolumePaths();
|
||||
Map<String, Long> volumeSizes = cmd.getVolumeSizes();
|
||||
Map<String, Long> progressMap = new HashMap<>();
|
||||
|
||||
if (transferIds == null || transferIds.isEmpty()) {
|
||||
return new GetImageTransferProgressAnswer(cmd, true, "No transfers to check", progressMap);
|
||||
}
|
||||
|
||||
for (String transferId : transferIds) {
|
||||
String volumePath = volumePaths.get(transferId);
|
||||
Long volumeSize = volumeSizes.get(transferId);
|
||||
|
||||
if (volumePath == null || volumeSize == null || volumeSize == 0) {
|
||||
logger.warn("Missing volume path or size for transferId: {}", transferId);
|
||||
progressMap.put(transferId, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
File file = new File(volumePath);
|
||||
if (!file.exists()) {
|
||||
logger.warn("Volume file does not exist: {}", volumePath);
|
||||
progressMap.put(transferId, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
long currentSize = file.length();
|
||||
|
||||
if (volumePath.endsWith(".qcow2") || volumePath.endsWith(".qcow")) {
|
||||
try {
|
||||
currentSize = KVMPhysicalDisk.getVirtualSizeFromFile(volumePath);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to get virtual size for qcow2 file: {}, using physical size", volumePath, e);
|
||||
}
|
||||
}
|
||||
progressMap.put(transferId, currentSize);
|
||||
logger.debug("Transfer {} progress, current: {})", transferId, currentSize, volumeSize);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error getting progress for transferId: {}, path: {}", transferId, volumePath, e);
|
||||
progressMap.put(transferId, null);
|
||||
}
|
||||
}
|
||||
|
||||
return new GetImageTransferProgressAnswer(cmd, true, "Progress retrieved successfully", progressMap);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error executing GetImageTransferProgressCommand", e);
|
||||
return new GetImageTransferProgressAnswer(cmd, false, "Error getting transfer progress: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ public class ImageTransferVOToImageTransferConverter {
|
|||
final String basePath = VeeamControlService.ContextPath.value();
|
||||
imageTransfer.setId(vo.getUuid());
|
||||
imageTransfer.setHref(basePath + ImageTransfersRouteHandler.BASE_ROUTE + "/" + vo.getUuid());
|
||||
imageTransfer.setActive(Boolean.toString(vo.getProgress() != null && vo.getProgress() > 0 && vo.getProgress() < 100));
|
||||
imageTransfer.setActive(Boolean.toString(org.apache.cloudstack.backup.ImageTransfer.Phase.transferring.equals(vo.getPhase())));
|
||||
imageTransfer.setDirection(vo.getDirection().name());
|
||||
imageTransfer.setFormat("cow");
|
||||
imageTransfer.setInactivityTimeout(Integer.toString(3600));
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
|
@ -53,10 +50,8 @@ import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
|
|||
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
||||
import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
|
||||
import org.apache.cloudstack.jobs.JobInfo;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -84,7 +79,6 @@ import com.cloud.user.AccountService;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.ReflectionUse;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
|
@ -142,8 +136,6 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup
|
|||
@Inject
|
||||
AsyncJobManager asyncJobManager;
|
||||
|
||||
private ScheduledExecutorService imageTransferStatusExecutor;
|
||||
|
||||
VmWorkJobHandlerProxy jobHandlerProxy = new VmWorkJobHandlerProxy(this);
|
||||
|
||||
private boolean isKVMBackupExportServiceSupported(Long zoneId) {
|
||||
|
|
@ -878,7 +870,6 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup
|
|||
response.setDiskId(volume.getUuid());
|
||||
response.setTransferUrl(imageTransferVO.getTransferUrl());
|
||||
response.setPhase(imageTransferVO.getPhase().toString());
|
||||
response.setProgress(imageTransferVO.getProgress());
|
||||
response.setDirection(imageTransferVO.getDirection().toString());
|
||||
response.setCreated(imageTransferVO.getCreated());
|
||||
return response;
|
||||
|
|
@ -886,24 +877,11 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup
|
|||
|
||||
@Override
|
||||
public boolean start() {
|
||||
imageTransferStatusExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Image-Transfer-Status-Executor"));
|
||||
long pollingInterval = ImageTransferPollingInterval.value();
|
||||
imageTransferStatusExecutor.scheduleAtFixedRate(new ManagedContextRunnable() {
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
try {
|
||||
pollImageTransferProgress();
|
||||
} catch (final Throwable t) {
|
||||
logger.warn("Catch throwable in image transfer poll task ", t);
|
||||
}
|
||||
}
|
||||
}, pollingInterval, pollingInterval, TimeUnit.SECONDS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
imageTransferStatusExecutor.shutdown();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -945,91 +923,6 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup
|
|||
}
|
||||
}
|
||||
|
||||
private void pollImageTransferProgress() {
|
||||
try {
|
||||
List<ImageTransferVO> transferringTransfers = imageTransferDao.listByPhaseAndDirection(
|
||||
ImageTransfer.Phase.transferring, ImageTransfer.Direction.upload);
|
||||
if (transferringTransfers == null || transferringTransfers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Long, List<ImageTransferVO>> transfersByHost = transferringTransfers.stream()
|
||||
.collect(Collectors.groupingBy(ImageTransferVO::getHostId));
|
||||
Map<Long, VolumeVO> transferVolumeMap = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Long, List<ImageTransferVO>> entry : transfersByHost.entrySet()) {
|
||||
Long hostId = entry.getKey();
|
||||
List<ImageTransferVO> hostTransfers = entry.getValue();
|
||||
|
||||
try {
|
||||
List<String> transferIds = new ArrayList<>();
|
||||
Map<String, String> volumePaths = new HashMap<>();
|
||||
Map<String, Long> volumeSizes = new HashMap<>();
|
||||
|
||||
for (ImageTransferVO transfer : hostTransfers) {
|
||||
VolumeVO volume = volumeDao.findById(transfer.getVolumeId());
|
||||
if (volume == null) {
|
||||
logger.warn("Volume not found for image transfer: {}", transfer.getUuid());
|
||||
imageTransferDao.remove(transfer.getId());
|
||||
continue;
|
||||
}
|
||||
transferVolumeMap.put(transfer.getId(), volume);
|
||||
|
||||
String transferId = transfer.getUuid();
|
||||
transferIds.add(transferId);
|
||||
|
||||
if (volume.getPath() == null) {
|
||||
logger.warn("Volume path is null for image transfer: {}", transfer.getUuid());
|
||||
continue;
|
||||
}
|
||||
String volumePath = getVolumePathForFileBasedBackend(volume);
|
||||
volumePaths.put(transferId, volumePath);
|
||||
volumeSizes.put(transferId, volume.getSize());
|
||||
}
|
||||
|
||||
if (transferIds.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GetImageTransferProgressCommand cmd = new GetImageTransferProgressCommand(transferIds, volumePaths, volumeSizes);
|
||||
GetImageTransferProgressAnswer answer = (GetImageTransferProgressAnswer) agentManager.send(hostId, cmd);
|
||||
|
||||
if (answer == null || !answer.getResult() || MapUtils.isEmpty(answer.getProgressMap())) {
|
||||
logger.warn("Failed to get progress for transfers on host {}: {}", hostId,
|
||||
answer != null ? answer.getDetails() : "null answer");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ImageTransferVO transfer : hostTransfers) {
|
||||
String transferId = transfer.getUuid();
|
||||
Long currentSize = answer.getProgressMap().get(transferId);
|
||||
if (currentSize == null) {
|
||||
continue;
|
||||
}
|
||||
VolumeVO volume = transferVolumeMap.get(transfer.getId());
|
||||
long totalSize = getVolumeTotalSize(volume);
|
||||
int progress = Math.max((int)((currentSize * 100) / totalSize), 100);
|
||||
transfer.setProgress(progress);
|
||||
if (currentSize >= 100) {
|
||||
transfer.setPhase(ImageTransfer.Phase.finished);
|
||||
logger.debug("Updated phase for image transfer {} to finished", transferId);
|
||||
}
|
||||
imageTransferDao.update(transfer.getId(), transfer);
|
||||
logger.debug("Updated progress for image transfer {}: {}%", transferId, progress);
|
||||
}
|
||||
|
||||
} catch (AgentUnavailableException | OperationTimedoutException e) {
|
||||
logger.warn("Failed to communicate with host {} for image transfer progress", hostId);
|
||||
} catch (Exception e) {
|
||||
logger.error("Error polling image transfer progress for host " + hostId, e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error in pollImageTransferProgress", e);
|
||||
}
|
||||
}
|
||||
|
||||
private long getVolumeTotalSize(VolumeVO volume) {
|
||||
VolumeDetailVO detail = volumeDetailsDao.findDetail(volume.getId(), ApiConstants.VIRTUAL_SIZE);
|
||||
if (detail != null) {
|
||||
|
|
@ -1063,7 +956,6 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup
|
|||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey[]{
|
||||
ImageTransferPollingInterval,
|
||||
ImageTransferIdleTimeoutSeconds,
|
||||
ExposeKVMBackupExportServiceApis
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue