package org.zstack.storage.primary.local;
import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.cloudbus.CloudBusCallBack;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.core.timeout.ApiTimeoutManager;
import org.zstack.header.HasThreadContext;
import org.zstack.header.core.ApiTimeout;
import org.zstack.header.core.Completion;
import org.zstack.header.core.ReturnValueCompletion;
import org.zstack.header.host.HostConstant;
import org.zstack.header.image.APICreateRootVolumeTemplateFromRootVolumeMsg;
import org.zstack.header.image.APICreateRootVolumeTemplateFromVolumeSnapshotMsg;
import org.zstack.header.message.MessageReply;
import org.zstack.header.storage.backup.BackupStorageConstant;
import org.zstack.header.storage.backup.BackupStorageInventory;
import org.zstack.header.storage.primary.PrimaryStorageInventory;
import org.zstack.header.vm.APICreateVmInstanceMsg;
import org.zstack.kvm.KVMConstant;
import org.zstack.kvm.KVMHostAsyncHttpCallMsg;
import org.zstack.kvm.KVMHostAsyncHttpCallReply;
import org.zstack.storage.backup.sftp.GetSftpBackupStorageDownloadCredentialMsg;
import org.zstack.storage.backup.sftp.GetSftpBackupStorageDownloadCredentialReply;
import org.zstack.storage.backup.sftp.SftpBackupStorageConstant;
import static org.zstack.core.Platform.operr;
import java.util.List;
import static org.zstack.utils.CollectionDSL.list;
/**
* Created by frank on 7/1/2015.
*/
@ApiTimeout(apiClasses = {APICreateVmInstanceMsg.class})
public class LocalStorageKvmSftpBackupStorageMediatorImpl implements LocalStorageBackupStorageMediator {
@Autowired
private CloudBus bus;
@Autowired
private ErrorFacade errf;
@Autowired
private ApiTimeoutManager timeoutMgr;
public static final String UPLOAD_BIT_PATH = "/localstorage/sftp/upload";
public static final String DOWNLOAD_BIT_PATH = "/localstorage/sftp/download";
@ApiTimeout(apiClasses = {APICreateVmInstanceMsg.class, APILocalStorageMigrateVolumeMsg.class})
public static class SftpDownloadBitsCmd extends LocalStorageKvmBackend.AgentCommand implements HasThreadContext {
private String sshKey;
private String username;
private String hostname;
private int sshPort;
private String backupStorageInstallPath;
private String primaryStorageInstallPath;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getSshPort() {
return sshPort;
}
public void setSshPort(int sshPort) {
this.sshPort = sshPort;
}
public String getSshKey() {
return sshKey;
}
public void setSshKey(String sshKey) {
this.sshKey = sshKey;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getBackupStorageInstallPath() {
return backupStorageInstallPath;
}
public void setBackupStorageInstallPath(String backupStorageInstallPath) {
this.backupStorageInstallPath = backupStorageInstallPath;
}
public String getPrimaryStorageInstallPath() {
return primaryStorageInstallPath;
}
public void setPrimaryStorageInstallPath(String primaryStorageInstallPath) {
this.primaryStorageInstallPath = primaryStorageInstallPath;
}
}
public static class SftpDownloadBitsRsp extends LocalStorageKvmBackend.AgentResponse {
}
@ApiTimeout(apiClasses = {
APICreateRootVolumeTemplateFromVolumeSnapshotMsg.class,
APICreateRootVolumeTemplateFromRootVolumeMsg.class
})
public static class SftpUploadBitsCmd extends LocalStorageKvmBackend.AgentCommand {
private String primaryStorageInstallPath;
private String backupStorageInstallPath;
private String hostname;
private String sshKey;
private String username;
private int sshPort;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getSshPort() {
return sshPort;
}
public void setSshPort(int sshPort) {
this.sshPort = sshPort;
}
public String getPrimaryStorageInstallPath() {
return primaryStorageInstallPath;
}
public void setPrimaryStorageInstallPath(String primaryStorageInstallPath) {
this.primaryStorageInstallPath = primaryStorageInstallPath;
}
public String getBackupStorageInstallPath() {
return backupStorageInstallPath;
}
public void setBackupStorageInstallPath(String backupStorageInstallPath) {
this.backupStorageInstallPath = backupStorageInstallPath;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getSshKey() {
return sshKey;
}
public void setSshKey(String sshKey) {
this.sshKey = sshKey;
}
}
public static class SftpUploadBitsRsp extends LocalStorageKvmBackend.AgentResponse {
}
public void downloadBits(final PrimaryStorageInventory pinv, BackupStorageInventory bsinv, final String backupStorageInstallPath, final String primaryStorageInstallPath, final String hostUuid, final Completion completion) {
GetSftpBackupStorageDownloadCredentialMsg gmsg = new GetSftpBackupStorageDownloadCredentialMsg();
gmsg.setBackupStorageUuid(bsinv.getUuid());
bus.makeTargetServiceIdByResourceUuid(gmsg, BackupStorageConstant.SERVICE_ID, bsinv.getUuid());
bus.send(gmsg, new CloudBusCallBack(completion) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
completion.fail(reply.getError());
return;
}
final GetSftpBackupStorageDownloadCredentialReply greply = reply.castReply();
SftpDownloadBitsCmd cmd = new SftpDownloadBitsCmd();
cmd.setHostname(greply.getHostname());
cmd.setUsername(greply.getUsername());
cmd.setSshKey(greply.getSshKey());
cmd.setSshPort(greply.getSshPort());
cmd.setBackupStorageInstallPath(backupStorageInstallPath);
cmd.setPrimaryStorageInstallPath(primaryStorageInstallPath);
cmd.storagePath = pinv.getUrl();
KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg();
msg.setHostUuid(hostUuid);
msg.setPath(DOWNLOAD_BIT_PATH);
msg.setCommand(cmd);
msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m"));
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hostUuid);
bus.send(msg, new CloudBusCallBack(completion) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
completion.fail(reply.getError());
return;
}
KVMHostAsyncHttpCallReply kr = reply.castReply();
SftpDownloadBitsRsp rsp = kr.toResponse(SftpDownloadBitsRsp.class);
if (!rsp.isSuccess()) {
completion.fail(operr("failed to download bits from the SFTP backup storage[hostname:%s, path: %s] to the local primary storage[uuid:%s, path: %s], %s",
greply.getHostname(), backupStorageInstallPath, pinv.getUuid(), primaryStorageInstallPath, rsp.getError()));
return;
}
completion.success();
}
});
}
});
}
@Override
public void uploadBits(final String imageUuid, final PrimaryStorageInventory pinv, BackupStorageInventory bsinv, final String backupStorageInstallPath, final String primaryStorageInstallPath, final String hostUuid, final ReturnValueCompletion<String> completion) {
GetSftpBackupStorageDownloadCredentialMsg gmsg = new GetSftpBackupStorageDownloadCredentialMsg();
gmsg.setBackupStorageUuid(bsinv.getUuid());
bus.makeTargetServiceIdByResourceUuid(gmsg, BackupStorageConstant.SERVICE_ID, bsinv.getUuid());
bus.send(gmsg, new CloudBusCallBack(completion) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
completion.fail(reply.getError());
return;
}
final GetSftpBackupStorageDownloadCredentialReply r = reply.castReply();
SftpUploadBitsCmd cmd = new SftpUploadBitsCmd();
cmd.setPrimaryStorageInstallPath(primaryStorageInstallPath);
cmd.setBackupStorageInstallPath(backupStorageInstallPath);
cmd.setHostname(r.getHostname());
cmd.setSshKey(r.getSshKey());
cmd.setSshPort(r.getSshPort());
cmd.setUsername(r.getUsername());
cmd.storagePath = pinv.getUrl();
KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg();
msg.setCommand(cmd);
msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m"));
msg.setPath(UPLOAD_BIT_PATH);
msg.setHostUuid(hostUuid);
bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hostUuid);
bus.send(msg, new CloudBusCallBack(completion) {
@Override
public void run(MessageReply reply) {
if (!reply.isSuccess()) {
completion.fail(reply.getError());
return;
}
KVMHostAsyncHttpCallReply kr = reply.castReply();
SftpUploadBitsRsp rsp = kr.toResponse(SftpUploadBitsRsp.class);
if (!rsp.isSuccess()) {
completion.fail(operr("failed to upload bits from the local storage[uuid:%s, path:%s] to the SFTP backup storage[hostname:%s, path:%s], %s",
pinv.getUuid(), primaryStorageInstallPath, r.getHostname(), backupStorageInstallPath, rsp.getError()));
return;
}
completion.success(backupStorageInstallPath);
}
});
}
});
}
@Override
public String getSupportedPrimaryStorageType() {
return LocalStorageConstants.LOCAL_STORAGE_TYPE;
}
@Override
public String getSupportedBackupStorageType() {
return SftpBackupStorageConstant.SFTP_BACKUP_STORAGE_TYPE;
}
@Override
public List<String> getSupportedHypervisorTypes() {
return list(KVMConstant.KVM_HYPERVISOR_TYPE);
}
}