package org.zstack.storage.fusionstor.primary; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.core.timeout.ApiTimeoutManager; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.host.HostConstant; import org.zstack.header.message.MessageReply; import org.zstack.header.vm.VmInstanceInventory; import org.zstack.header.vm.VmInstanceMigrateExtensionPoint; import org.zstack.header.volume.VolumeInventory; import org.zstack.kvm.KVMAgentCommands.AgentCommand; import org.zstack.kvm.KVMAgentCommands.AgentResponse; import org.zstack.kvm.KVMHostAsyncHttpCallMsg; import org.zstack.kvm.KVMHostAsyncHttpCallReply; import org.zstack.storage.fusionstor.FusionstorConstants; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import javax.persistence.TypedQuery; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Created by frank on 6/16/2015. */ public class FusionstorPrimaryStorageVmMigrationExtension implements VmInstanceMigrateExtensionPoint { public static final String KVM_FUSIONSTOR_QUERY_PATH = "/fusionstor/query"; public static class FusionstorQueryRsp extends AgentResponse { public String rsp; } public static class FusionstorQueryCmd extends AgentCommand { public String query; } private CLogger logger = Utils.getLogger(FusionstorPrimaryStorageVmMigrationExtension.class); private Map<String, List<VolumeInventory>> vmVolumes = new ConcurrentHashMap<String, List<VolumeInventory>>(); @Autowired private CloudBus bus; @Autowired private DatabaseFacade dbf; @Autowired private ErrorFacade errf; @Autowired private ApiTimeoutManager timeoutMgr; @Transactional(readOnly = true) private boolean needLink(VmInstanceInventory inv) { String sql = "select ps.type from PrimaryStorageVO ps, VolumeVO vol where ps.uuid = vol.primaryStorageUuid" + " and vol.uuid = :uuid"; TypedQuery<String> q = dbf.getEntityManager().createQuery(sql, String.class); q.setParameter("uuid", inv.getRootVolumeUuid()); List<String> res = q.getResultList(); if (res.isEmpty()) { return false; } String type = res.get(0); return FusionstorConstants.FUSIONSTOR_PRIMARY_STORAGE_TYPE.equals(type); } @Override public void preMigrateVm(VmInstanceInventory inv, String destHostUuid) { if (!needLink(inv)) { return; } FusionstorQueryCmd cmd = new FusionstorQueryCmd(); cmd.query = "query"; KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg(); msg.setCommand(cmd); msg.setCommandTimeout(timeoutMgr.getTimeout(cmd.getClass(), "5m")); msg.setPath(KVM_FUSIONSTOR_QUERY_PATH); msg.setHostUuid(destHostUuid); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, destHostUuid); MessageReply reply = bus.call(msg); if (!reply.isSuccess()) { throw new OperationFailureException(reply.getError()); } KVMHostAsyncHttpCallReply r = reply.castReply(); FusionstorQueryRsp rsp = r.toResponse(FusionstorQueryRsp.class); if (!rsp.isSuccess()) { throw new OperationFailureException(errf.stringToOperationError(rsp.getError())); } return; } @Override public void beforeMigrateVm(VmInstanceInventory inv, String destHostUuid) { } @Override public void afterMigrateVm(VmInstanceInventory inv, String srcHostUuid) { } @Override public void failedToMigrateVm(VmInstanceInventory inv, String destHostUuid, ErrorCode reason) { } }