package org.zstack.kvm; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; import org.zstack.core.cloudbus.CloudBusSteppingCallback; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.core.timeout.ApiTimeoutManager; import org.zstack.header.core.AsyncBackup; import org.zstack.header.core.ReturnValueCompletion; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.host.HostConstant; import org.zstack.header.message.MessageReply; import org.zstack.header.message.NeedReplyMessage; import org.zstack.utils.DebugUtils; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static org.zstack.utils.CollectionDSL.list; /** * Created by xing5 on 2016/4/19. */ @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class KvmCommandSender { @Autowired private CloudBus bus; @Autowired private ApiTimeoutManager timeoutManager; @Autowired private ErrorFacade errf; private List<String> hostUuids; private boolean noStatusCheck; public static abstract class SteppingSendCallback<T> extends ReturnValueCompletion<T> { String hostUuid; public SteppingSendCallback() { super(null); } protected String getHostUuid() { return hostUuid; } } public KvmCommandSender(List<String> hostUuids, boolean noStatusCheck) { this.hostUuids = hostUuids; this.noStatusCheck = noStatusCheck; } public KvmCommandSender(List<String> hostUuids) { this(hostUuids, false); } public KvmCommandSender(String hostUuid) { this(hostUuid, false); } public KvmCommandSender(String hostUuid, boolean noStatusCheck) { this(list(hostUuid), noStatusCheck); DebugUtils.Assert(hostUuid != null, "hostUuid cannot be null"); } public void send(final Object cmd, final String path, final KvmCommandFailureChecker checker, final SteppingSendCallback<KvmResponseWrapper> completion) { send(cmd, path, checker, TimeUnit.MINUTES.toMillis(5), completion); } public void send(final Object cmd, final String path, final KvmCommandFailureChecker checker , final long defaulTimeout, final SteppingSendCallback<KvmResponseWrapper> completion) { List<KVMHostAsyncHttpCallMsg> msgs = hostUuids.stream().map(huuid -> { KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg(); msg.setCommand(cmd); msg.setCommandTimeout(timeoutManager.getTimeout(cmd.getClass(), defaulTimeout)); msg.setHostUuid(huuid); msg.setPath(path); msg.setNoStatusCheck(noStatusCheck); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, huuid); return msg; }).collect(Collectors.toList()); bus.send(msgs, msgs.size(), new CloudBusSteppingCallback(completion) { @Override public void run(NeedReplyMessage msg, MessageReply reply) { KVMHostAsyncHttpCallMsg kmsg = (KVMHostAsyncHttpCallMsg) msg; completion.hostUuid = kmsg.getHostUuid(); if (!reply.isSuccess()) { completion.fail(reply.getError()); return; } KVMHostAsyncHttpCallReply ar = reply.castReply(); KvmResponseWrapper w = new KvmResponseWrapper(ar.getResponse()); ErrorCode err = checker.getError(w); if (err != null) { completion.fail(err); return; } completion.success(w); } }); } public void send(final Object cmd, final String path, final KvmCommandFailureChecker checker, final ReturnValueCompletion<KvmResponseWrapper> completion) { send(cmd, path, checker, TimeUnit.MINUTES.toMillis(5), completion); } public void send(final Object cmd, final String path, final KvmCommandFailureChecker checker , final long defaulTimeout, final ReturnValueCompletion<KvmResponseWrapper> completion) { if (hostUuids.isEmpty()) { throw new CloudRuntimeException("no host uuid given"); } if (hostUuids.size() > 1) { throw new CloudRuntimeException("please use SteppingSendCallback"); } String huuid = hostUuids.get(0); KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg(); msg.setCommand(cmd); msg.setCommandTimeout(timeoutManager.getTimeout(cmd.getClass(), defaulTimeout)); msg.setHostUuid(huuid); msg.setPath(path); msg.setNoStatusCheck(noStatusCheck); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, huuid); bus.send(msg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { if (!reply.isSuccess()) { completion.fail(reply.getError()); return; } KVMHostAsyncHttpCallReply ar = reply.castReply(); KvmResponseWrapper w = new KvmResponseWrapper(ar.getResponse()); ErrorCode err = checker.getError(w); if (err != null) { completion.fail(err); return; } completion.success(w); } }); } }