Mercurial > hg > release > thermostat-1.4
changeset 1506:6222ea3f5803
Kill-VM Command Addition
reviewed-by: omajid
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-September/010859.html
line wrap: on
line diff
--- a/build-deps/pom.xml Fri Sep 26 15:19:39 2014 +0200 +++ b/build-deps/pom.xml Mon Sep 29 15:14:32 2014 -0400 @@ -277,5 +277,11 @@ <version>${project.version}</version> <type>zip</type> </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-killvm-distribution</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> </dependencies> </project>
--- a/distribution/assembly/all-plugin-assembly.xml Fri Sep 26 15:19:39 2014 +0200 +++ b/distribution/assembly/all-plugin-assembly.xml Mon Sep 29 15:14:32 2014 -0400 @@ -66,6 +66,7 @@ <include>com.redhat.thermostat:thermostat-vm-overview-distribution</include> <include>com.redhat.thermostat:thermostat-schema-info-distribution</include> <include>com.redhat.thermostat:thermostat-web-endpoint-distribution</include> + <include>com.redhat.thermostat:thermostat-killvm-distribution</include> </includes> </dependencySet> </dependencySets>
--- a/killvm/client-swing/pom.xml Fri Sep 26 15:19:39 2014 +0200 +++ b/killvm/client-swing/pom.xml Mon Sep 29 15:14:32 2014 -0400 @@ -24,9 +24,9 @@ com.redhat.thermostat.killvm.client.internal, com.redhat.thermostat.killvm.client.locale, </Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> </instructions> - <!-- Do not autogenerate uses clauses in Manifests --> - <_nouses>true</_nouses> </configuration> </plugin> </plugins>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/pom.xml Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012-2014 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses />. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-killvm</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-killvm-command</artifactId> + <packaging>bundle</packaging> + + <name>Thermostat Command Kill VM</name> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> + <Bundle-Activator>com.redhat.thermostat.killvm.command.internal.Activator</Bundle-Activator> + <Bundle-SymbolicName>com.redhat.thermostat.killvm.command</Bundle-SymbolicName> + <Export-Package> + com.redhat.thermostat.killvm.command, + </Export-Package> + <Private-Package> + com.redhat.thermostat.killvm.command.internal, + com.redhat.thermostat.killvm.command.locale, + </Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-command</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-shared-config</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-client-core</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/KillVMCommand.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,159 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command; + +import java.net.InetSocketAddress; + +import com.redhat.thermostat.client.cli.HostVMArguments; +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.common.cli.AbstractCommand; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.killvm.command.internal.ShellVMKilledListener; +import com.redhat.thermostat.killvm.command.locale.LocaleResources; +import com.redhat.thermostat.shared.locale.LocalizedString; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.VmInfo; + +public class KillVMCommand extends AbstractCommand { + + private static final String RECEIVER = "com.redhat.thermostat.killvm.agent.internal.KillVmReceiver"; + private static final String CMD_CHANNEL_ACTION_NAME = "killvm"; + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private final ShellVMKilledListener listener; + + private HostInfoDAO hostInfoDAO; + private VmInfoDAO vmInfoDAO; + private AgentInfoDAO agentInfoDAO; + private RequestQueue requestQueue; + + public KillVMCommand(ShellVMKilledListener listener) { + this.listener = listener; + } + + @Override + public void run(CommandContext ctx) throws CommandException { + requireNotNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE)); + requireNotNull(hostInfoDAO, translator.localize(LocaleResources.HOST_SERVICE_UNAVAILABLE)); + requireNotNull(agentInfoDAO, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE)); + requireNotNull(requestQueue, translator.localize(LocaleResources.QUEUE_SERVICE_UNAVAILABLE)); + + listener.setOut(ctx.getConsole().getOutput()); + listener.setErr(ctx.getConsole().getError()); + + HostVMArguments args = new HostVMArguments(ctx.getArguments(), true, true); + + attemptToKillVM(args.getVM()); + } + + private void requireNotNull(Object object, LocalizedString message) throws CommandException { + if (object == null) { + throw new CommandException(message); + } + } + + private void attemptToKillVM(VmRef vmRef) throws CommandException { + VmInfo result = vmInfoDAO.getVmInfo(vmRef); + + if (result == null) { + throw new CommandException(translator.localize(LocaleResources.VM_NOT_FOUND, vmRef.getVmId())); + } else { + sendKillRequest(vmRef.getHostRef(), result.getVmPid()); + } + } + + private void sendKillRequest(HostRef hostRef, int vmPid) throws CommandException { + InetSocketAddress target = getAddressFromHost(hostRef); + + Request murderer = setupMurderer(target, vmPid); + + requestQueue.putRequest(murderer); + + waitForListenerResponse(); + } + + private InetSocketAddress getAddressFromHost(HostRef hostRef) throws CommandException { + String [] hostAndPort = getHostAndPort(hostRef); + return new InetSocketAddress(hostAndPort[0], Integer.parseInt(hostAndPort[1])); + } + + private Request setupMurderer(InetSocketAddress target, int vmPid) { + Request murderer = new Request(Request.RequestType.RESPONSE_EXPECTED, target); + murderer.setParameter(Request.ACTION, CMD_CHANNEL_ACTION_NAME); + murderer.setParameter("vm-pid", String.valueOf(vmPid)); + murderer.setReceiver(RECEIVER); + murderer.addListener(listener); + + return murderer; + } + + private String[] getHostAndPort(HostRef hostRef) throws CommandException { + String address = agentInfoDAO.getAgentInformation(hostRef).getConfigListenAddress(); + return address.split(":"); + } + + private void waitForListenerResponse() throws CommandException { + try { + listener.await(1000l); + } catch (InterruptedException e) { + throw new CommandException(translator.localize(LocaleResources.KILL_INTERRUPTED)); + } + } + + public void setHostInfoDAO(HostInfoDAO hostInfoDAO) { + this.hostInfoDAO = hostInfoDAO; + } + + public void setVmInfoDAO(VmInfoDAO vmInfoDAO) { + this.vmInfoDAO = vmInfoDAO; + } + + public void setAgentInfoDAO(AgentInfoDAO agentInfoDAO) { + this.agentInfoDAO = agentInfoDAO; + } + + public void setRequestQueue(RequestQueue requestQueue) { + this.requestQueue = requestQueue; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.internal; + +import java.util.Hashtable; +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.cli.Command; +import com.redhat.thermostat.killvm.command.KillVMCommand; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; + +public class Activator implements BundleActivator { + + private ServiceRegistration killCommandRegistration; + private MultipleServiceTracker serviceTracker; + private KillVMCommand command = new KillVMCommand(new ShellVMKilledListener()); + + @Override + public void start(final BundleContext context) throws Exception { + Class<?>[] serviceDeps = new Class<?>[] { + HostInfoDAO.class, + AgentInfoDAO.class, + VmInfoDAO.class, + RequestQueue.class, + }; + + serviceTracker = new MultipleServiceTracker(context, serviceDeps, new MultipleServiceTracker.Action() { + @Override + public void dependenciesAvailable(Map<String, Object> services) { + HostInfoDAO hostDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName()); + AgentInfoDAO agentDao = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName()); + VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName()); + RequestQueue requestQueue = (RequestQueue) services.get(RequestQueue.class.getName()); + + command.setAgentInfoDAO(agentDao); + command.setHostInfoDAO(hostDAO); + command.setVmInfoDAO(vmDao); + command.setRequestQueue(requestQueue); + } + + @Override + public void dependenciesUnavailable() { + command.setAgentInfoDAO(null); + command.setHostInfoDAO(null); + command.setVmInfoDAO(null); + command.setRequestQueue(null); + } + }); + + serviceTracker.open(); + + Hashtable<String,String> properties = new Hashtable<>(); + properties.put(Command.NAME, "kill-vm"); + killCommandRegistration = context.registerService(Command.class.getName(), command, properties); + } + + @Override + public void stop(BundleContext context) throws Exception { + serviceTracker.close(); + killCommandRegistration.unregister(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/ShellVMKilledListener.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,102 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.internal; + +import java.io.PrintStream; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.common.command.RequestResponseListener; +import com.redhat.thermostat.common.command.Response; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class ShellVMKilledListener implements RequestResponseListener { + + private static final Logger logger = LoggingUtils + .getLogger(ShellVMKilledListener.class); + private boolean complete = false; + + private PrintStream out; + private PrintStream err; + + private CountDownLatch latch = new CountDownLatch(1); + + @Override + public void fireComplete(Request request, Response response) { + String message; + switch (response.getType()) { + case ERROR: + String pid = request.getParameter("vm-pid"); + message = "Kill request error for VM ID " + pid; + logger.log(Level.SEVERE, message); + if (err != null) { + err.println(message); + } + break; + case OK: + message = "VM with id " + request.getParameter("vm-pid") + " killed."; + logger.log(Level.INFO, message); + if (out != null) { + out.println(message); + } + break; + default: + message = "Unknown result from KILL VM command."; + logger.log(Level.WARNING, message); + if (out != null) { + out.println(message); + } + break; + } + latch.countDown(); + } + + public void setOut(PrintStream out) { + this.out = out; + } + + public void setErr(PrintStream err) { + this.err = err; + } + + public synchronized void await(long timeout) throws InterruptedException { + this.latch.await(timeout, TimeUnit.MILLISECONDS); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/locale/LocaleResources.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.locale; + +import com.redhat.thermostat.shared.locale.Translate; + +public enum LocaleResources { + + HOST_SERVICE_UNAVAILABLE, + VM_SERVICE_UNAVAILABLE, + AGENT_SERVICE_UNAVAILABLE, + QUEUE_SERVICE_UNAVAILABLE, + KILL_INTERRUPTED, + VM_NOT_FOUND; + + public static final String RESOURCE_BUNDLE = + "com.redhat.thermostat.killvm.command.locale.strings"; + + public static Translate<LocaleResources> createLocalizer() { + return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/main/resources/com/redhat/thermostat/killvm/command/locale/strings.properties Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,6 @@ +HOST_SERVICE_UNAVAILABLE = Unable to get host information (HostInfoDAO is unavailable) +VM_SERVICE_UNAVAILABLE = Unable to get vm information (VmInfoDAO is unavailable) +AGENT_SERVICE_UNAVAILABLE = Unable to get agent information (AgentInfoDAO is unavailable) +QUEUE_SERVICE_UNAVAILABLE = Unable to get queue information (RequestQueue is unavailable) +KILL_INTERRUPTED = Command interrupted while waiting for response from murderer +VM_NOT_FOUND = VM with ID {0} not found. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/KillVmCommandTest.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,170 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.SimpleArguments; +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.killvm.command.internal.ShellVMKilledListener; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.test.TestCommandContextFactory; + +public class KillVmCommandTest { + + private TestCommandContextFactory cmdCtxFactory; + private KillVMCommand cmd; + + private HostInfoDAO hostInfoDAO; + private VmInfoDAO vmInfoDAO; + private AgentInfoDAO agentInfoDAO; + + private ShellVMKilledListener listener; + private RequestQueue requestQueue; + + private HostRef hostRef; + private VmRef vmRef; + + + @Before + public void setup() { + cmdCtxFactory = new TestCommandContextFactory(); + + hostInfoDAO = mock(HostInfoDAO.class); + vmInfoDAO = mock(VmInfoDAO.class); + agentInfoDAO = mock(AgentInfoDAO.class); + + listener = mock(ShellVMKilledListener.class); + requestQueue = mock(RequestQueue.class); + + cmd = new KillVMCommand(listener); + cmd.setVmInfoDAO(vmInfoDAO); + cmd.setAgentInfoDAO(agentInfoDAO); + cmd.setHostInfoDAO(hostInfoDAO); + cmd.setRequestQueue(requestQueue); + + hostRef = new HostRef("10", "dummy"); + vmRef = new VmRef(hostRef, "liveVM", -1, "dummy"); + + VmInfo vmInfo = mock(VmInfo.class); + when(vmInfo.getVmPid()).thenReturn(-1); + + when(vmInfoDAO.getVmInfo(vmRef)).thenReturn(vmInfo); + } + + @Test + public void testKillLiveVM() throws CommandException, InterruptedException { + String vmId = "liveVM"; + + AgentInformation agent = mock(AgentInformation.class); + when(agent.getConfigListenAddress()).thenReturn("addr:10"); + when(agentInfoDAO.getAgentInformation(hostRef)).thenReturn(agent); + + CommandContext ctx = createContext(vmId, hostRef.getAgentId()); + + final boolean[] complete = {false}; + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + complete[0] = true; + return null; + } + }).when(requestQueue).putRequest(any(Request.class)); + + cmd.run(ctx); + + assertTrue(complete[0]); + } + + @Test(expected = CommandException.class) + public void testKillNonexistentVM() throws CommandException { + String vmId = "nonexistentVM"; + CommandContext ctx = createContext(vmId, hostRef.getAgentId()); + cmd.run(ctx); + } + + @Test(expected = CommandException.class) + public void testKillNonexistentHost() throws CommandException { + String vmId = "liveVM"; + CommandContext ctx = createContext(vmId, "nonexistentHost"); + cmd.run(ctx); + } + + @Test(expected = CommandException.class) + public void testNoVMArgument() throws CommandException { + SimpleArguments args = new SimpleArguments(); + args.addArgument("hostId", "hostId"); + CommandContext ctx = cmdCtxFactory.createContext(args); + + cmd.run(ctx); + } + + @Test(expected = CommandException.class) + public void testNoHostArgument() throws CommandException { + SimpleArguments args = new SimpleArguments(); + args.addArgument("vmId", "vmId"); + CommandContext ctx = cmdCtxFactory.createContext(args); + + cmd.run(ctx); + } + + public CommandContext createContext(String vmId, String hostId) { + SimpleArguments args = new SimpleArguments(); + args.addArgument("vmId", vmId); + args.addArgument("hostId", hostId); + return cmdCtxFactory.createContext(args); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/ActivatorTest.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.internal; + +import static com.redhat.thermostat.testutils.Asserts.assertCommandIsRegistered; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.redhat.thermostat.killvm.command.KillVMCommand; +import com.redhat.thermostat.testutils.StubBundleContext; + +public class ActivatorTest { + @Test + public void verifyActivatorRegistersServices() throws Exception { + StubBundleContext context = new StubBundleContext(); + Activator activator = new Activator(); + + activator.start(context); + + assertCommandIsRegistered(context, "kill-vm", KillVMCommand.class); + + activator.stop(context); + + assertEquals(0, context.getServiceListeners().size()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/ShellVMKilledListenerTest.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,140 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.internal; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.common.command.Response; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class ShellVMKilledListenerTest { + + private final ShellVMKilledListener listener = new ShellVMKilledListener(); + private static final Logger logger = LoggingUtils + .getLogger(ShellVMKilledListener.class); + + + @Test + public void testSuccessfulKillResponse() { + Request request = mock(Request.class); + + Response resp = new Response(Response.ResponseType.OK); + + Handler handler = mock(Handler.class); + logger.addHandler(handler); + + final boolean[] complete = {false}; + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + LogRecord log = (LogRecord)invocation.getArguments()[0]; + if (log.getLevel().equals(Level.INFO)) { + complete[0] = true; + } + return null; + } + }).when(handler).publish(any(LogRecord.class)); + + listener.fireComplete(request, resp); + + assertTrue(complete[0]); + } + + @Test + public void testErrorResponse() { + Request request = mock(Request.class); + Response resp = new Response(Response.ResponseType.ERROR); + + Handler handler = mock(Handler.class); + logger.addHandler(handler); + + final boolean[] complete = {false}; + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + LogRecord log = (LogRecord)invocation.getArguments()[0]; + if (log.getLevel().equals(Level.SEVERE)) { + complete[0] = true; + } + return null; + } + }).when(handler).publish(any(LogRecord.class)); + + listener.fireComplete(request, resp); + + assertTrue(complete[0]); + } + + @Test + public void testDefaultResponse() { + Request request = mock(Request.class); + Response resp = new Response(Response.ResponseType.NOK); + + Handler handler = mock(Handler.class); + logger.addHandler(handler); + + final boolean[] complete = {false}; + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + LogRecord log = (LogRecord)invocation.getArguments()[0]; + if (log.getLevel().equals(Level.WARNING)) { + complete[0] = true; + } + return null; + } + }).when(handler).publish(any(LogRecord.class)); + + listener.fireComplete(request, resp); + + assertTrue(complete[0]); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/locale/LocaleResourcesTest.java Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.killvm.command.locale; + +import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest; + +public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> { + + @Override + protected Class<LocaleResources> getEnumClass() { + return LocaleResources.class; + } + + @Override + protected String getResourceBundle() { + return LocaleResources.RESOURCE_BUNDLE; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/distribution/pom.xml Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012-2014 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses />. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-killvm</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-killvm-distribution</artifactId> + <packaging>pom</packaging> + + <name>Thermostat KillVM Distribution</name> + + <properties> + <thermostat.plugin>killvm</thermostat.plugin> + </properties> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <dependencies> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-assembly</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <configuration> + <descriptorRefs> + <descriptorRef>plugin-assembly</descriptorRef> + </descriptorRefs> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>assemble-plugin</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <!-- Explicitly list all plug-in artifacts, transitive dependencies + are not included in assembly. --> + <dependencies> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-killvm-command</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/killvm/distribution/thermostat-plugin.xml Mon Sep 29 15:14:32 2014 -0400 @@ -0,0 +1,89 @@ +<?xml version="1.0"?> +<!-- + + Copyright 2012-2014 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + Thermostat is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses />. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd"> + <commands> + <command> + <name>kill-vm</name> + <description>Attempts to kill the vm specified.</description> + <options> + <option> + <long>vmId</long> + <short>v</short> + <argument>vmId</argument> + <required>true</required> + <description>the ID of the VM</description> + </option> + <option> + <long>hostId</long> + <short>h</short> + <argument>host</argument> + <required>true</required> + <description>the ID of the Host</description> + </option> + </options> + <environments> + <environment>cli</environment> + <environment>shell</environment> + </environments> + <bundles> + <bundle><symbolic-name>com.redhat.thermostat.killvm.command</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>org.mongodb.mongo-java-driver</symbolic-name><version>${mongo-driver.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.core.version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.client.version}</version></bundle> + <bundle><symbolic-name>${osgi.compendium.bundle.symbolic-name}</symbolic-name><version>${osgi.compendium.osgi-version}</version></bundle> + <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle> + <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle> + </bundles> + </command> + </commands> +</plugin> +