package org.zstack.kvm; 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.header.allocator.HostAllocatorConstant; import org.zstack.header.allocator.UnableToReserveHostCapacityException; import org.zstack.header.cluster.ReportHostCapacityMessage; import org.zstack.header.core.Completion; import org.zstack.header.core.NopeCompletion; import org.zstack.header.core.workflow.Flow; import org.zstack.header.core.workflow.FlowTrigger; import org.zstack.header.core.workflow.NoRollbackFlow; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.host.*; import org.zstack.header.message.MessageReply; import org.zstack.kvm.KVMAgentCommands.HostCapacityCmd; import org.zstack.kvm.KVMAgentCommands.HostCapacityResponse; import org.zstack.utils.SizeUtils; import java.util.Map; import static org.zstack.core.Platform.operr; public class KVMHostCapacityExtension implements KVMHostConnectExtensionPoint, HostConnectionReestablishExtensionPoint { @Autowired private CloudBus bus; @Autowired private ErrorFacade errf; private void reportCapacity(HostInventory host, Completion completion) { KVMHostSyncHttpCallMsg msg = new KVMHostSyncHttpCallMsg(); msg.setHostUuid(host.getUuid()); msg.setPath(KVMConstant.KVM_HOST_CAPACITY_PATH); msg.setNoStatusCheck(true); msg.setCommand(new HostCapacityCmd()); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, host.getUuid()); MessageReply reply = bus.call(msg); if (!reply.isSuccess()) { throw new OperationFailureException(reply.getError()); } KVMHostSyncHttpCallReply r = reply.castReply(); HostCapacityResponse rsp = r.toResponse(HostCapacityResponse.class); if (!rsp.isSuccess()) { throw new OperationFailureException(operr(rsp.getError())); } if (rsp.getTotalMemory() < SizeUtils.sizeStringToBytes(KVMGlobalConfig.RESERVED_MEMORY_CAPACITY.value())) { throw new UnableToReserveHostCapacityException(String.format("The host[uuid:%s]'s memory capacity[%s] is lower than the minimal required capacity[%s]", host.getUuid(), rsp.getTotalMemory(), SizeUtils.sizeStringToBytes(KVMGlobalConfig.RESERVED_MEMORY_CAPACITY.value()))); } ReportHostCapacityMessage rmsg = new ReportHostCapacityMessage(); rmsg.setHostUuid(host.getUuid()); rmsg.setCpuNum((int) rsp.getCpuNum()); rmsg.setUsedCpu(rsp.getUsedCpu()); rmsg.setTotalMemory(rsp.getTotalMemory()); rmsg.setUsedMemory(rsp.getUsedMemory()); rmsg.setCpuSockets(rsp.getCpuSockets()); rmsg.setServiceId(bus.makeLocalServiceId(HostAllocatorConstant.SERVICE_ID)); bus.send(rmsg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { if (!reply.isSuccess()) { completion.fail(reply.getError()); } else { completion.success(); } } }); } @Override public void connectionReestablished(HostInventory inv) throws HostException { reportCapacity(inv, new NopeCompletion()); } @Override public HypervisorType getHypervisorTypeForReestablishExtensionPoint() { return HypervisorType.valueOf(KVMConstant.KVM_HYPERVISOR_TYPE); } @Override public Flow createKvmHostConnectingFlow(final KVMHostConnectedContext context) { return new NoRollbackFlow() { String __name__ = "sync-host-capacity"; @Override public void run(FlowTrigger trigger, Map data) { reportCapacity(context.getInventory(), new Completion(trigger) { @Override public void success() { trigger.next(); } @Override public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } }); } }; } }