package com.neverwinterdp.vm.client; import static com.neverwinterdp.vm.tool.VMClusterBuilder.h1; import java.util.List; import com.mycila.jmx.annotation.JmxBean; import com.neverwinterdp.registry.Node; import com.neverwinterdp.registry.NodeCreateMode; import com.neverwinterdp.registry.Registry; import com.neverwinterdp.registry.RegistryException; import com.neverwinterdp.registry.event.NodeEvent; import com.neverwinterdp.registry.event.NodeWatcher; import com.neverwinterdp.vm.VMConfig; import com.neverwinterdp.vm.VMDescriptor; import com.neverwinterdp.vm.command.Command; import com.neverwinterdp.vm.command.CommandPayload; import com.neverwinterdp.vm.command.CommandResult; import com.neverwinterdp.vm.command.VMCommand; import com.neverwinterdp.vm.event.VMShutdownEventListener; import com.neverwinterdp.vm.service.VMService; import com.neverwinterdp.vm.service.VMServiceCommand; @JmxBean("role=vm-client, type=VMClient, name=VMClient") public class VMClient { private Registry registry; public VMClient(Registry registry) { this.registry = registry; } public Registry getRegistry() { return this.registry ; } public List<VMDescriptor> getRunningVMDescriptors() throws RegistryException { return registry.getChildrenAs(VMService.ALLOCATED_PATH, VMDescriptor.class) ; } public List<VMDescriptor> getHistoryVMDescriptors() throws RegistryException { return registry.getChildrenAs(VMService.HISTORY_PATH, VMDescriptor.class) ; } public VMDescriptor getMasterVMDescriptor() throws RegistryException { Node vmNode = registry.getRef(VMService.LEADER_PATH); return vmNode.getDataAs(VMDescriptor.class); } public void shutdown() throws Exception { h1("Shutdow the vm masters"); registry.create(VMShutdownEventListener.EVENT_PATH, true, NodeCreateMode.PERSISTENT); } public CommandResult<?> execute(VMDescriptor vmDescriptor, Command command) throws RegistryException, Exception { return execute(vmDescriptor, command, 30000); } public CommandResult<?> execute(VMDescriptor vmDescriptor, Command command, long timeout) throws RegistryException, Exception { CommandPayload payload = new CommandPayload(command, null) ; Node node = registry.create(vmDescriptor.getStoredPath() + "/commands/command-", payload, NodeCreateMode.EPHEMERAL_SEQUENTIAL); CommandReponseWatcher responseWatcher = new CommandReponseWatcher(); node.watch(responseWatcher); return responseWatcher.waitForResult(timeout); } public void execute(VMDescriptor vmDescriptor, Command command, CommandCallback callback) { } public VMDescriptor allocate(VMConfig vmConfig) throws Exception { VMDescriptor masterVMDescriptor = getMasterVMDescriptor(); CommandResult<VMDescriptor> result = (CommandResult<VMDescriptor>) execute(masterVMDescriptor, new VMServiceCommand.Allocate(vmConfig)); if(result.getErrorStacktrace() != null) { registry.get("/").dump(System.err); throw new Exception(result.getErrorStacktrace()); } return result.getResult(); } public VMDescriptor allocate(String localAppHome, VMConfig vmConfig) throws Exception { return allocate(vmConfig); } public boolean shutdown(VMDescriptor vmDescriptor) throws Exception { CommandResult<?> result = execute(vmDescriptor, new VMCommand.Shutdown()); return result.getResultAs(Boolean.class); } public void uploadApp(String localAppHome, String appHome) throws Exception { } public void createVMMaster(String name) throws Exception { throw new RuntimeException("This method need to override") ; } public void configureEnvironment(VMConfig vmConfig) { throw new RuntimeException("This method need to override") ; } public class CommandReponseWatcher extends NodeWatcher { private CommandResult<?> result ; private Exception error ; @Override public void onEvent(NodeEvent event) { String path = event.getPath(); try { CommandPayload payload = registry.getDataAs(path, CommandPayload.class) ; result = payload.getResult() ; registry.delete(path); synchronized(this) { notify(); } } catch(Exception e) { error = e ; } } public CommandResult<?> waitForResult(long timeout) throws Exception { if(result == null) { synchronized(this) { wait(timeout); } } if(error != null) throw error; return result ; } } }