Mercurial > hg > release > thermostat-0.4
changeset 307:5d4d4d1a0cf7
Implement VMInfoCommand.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-May/001350.html
author | Roman Kennke <rkennke@redhat.com> |
---|---|
date | Wed, 16 May 2012 15:20:08 +0200 |
parents | 724f56f1a360 |
children | edd01fa07b0d |
files | common/src/main/java/com/redhat/thermostat/common/dao/DAOException.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java tools/src/main/java/com/redhat/thermostat/tools/cli/VMInfoCommand.java tools/src/main/java/com/redhat/thermostat/tools/cli/VMListFormatter.java tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command tools/src/test/java/com/redhat/thermostat/tools/cli/ListVMsCommandTest.java tools/src/test/java/com/redhat/thermostat/tools/cli/VMInfoCommandTest.java |
diffstat | 8 files changed, 410 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOException.java Wed May 16 15:20:08 2012 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright 2012 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.common.dao; + +public class DAOException extends RuntimeException { + + public DAOException() { + super(); + } + + public DAOException(String message) { + super(message); + } + + public DAOException(Throwable cause) { + super(cause); + } + + public DAOException(String message, Throwable cause) { + super(message, cause); + } + +}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java Tue May 15 16:09:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java Wed May 16 15:20:08 2012 +0200 @@ -62,6 +62,9 @@ query.put(Key.AGENT_ID, ref.getAgent().getAgentId()); query.put(vmIdKey, ref.getId()); Chunk result = storage.find(query); + if (result == null) { + throw new DAOException("Unknown VM: host:" + ref.getAgent().getAgentId() + ";vm:" + ref.getId()); + } return converter.fromChunk(result); }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java Tue May 15 16:09:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java Wed May 16 15:20:08 2012 +0200 @@ -36,7 +36,7 @@ package com.redhat.thermostat.common.dao; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; @@ -177,6 +177,28 @@ // FIXME test environment, properties and loaded native libraries later } + @Test + public void testGetVmInfoUnknownVM() { + + Storage storage = mock(Storage.class); + + HostRef hostRef = mock(HostRef.class); + when(hostRef.getAgentId()).thenReturn("system"); + + VmRef vmRef = mock(VmRef.class); + when(vmRef.getAgent()).thenReturn(hostRef); + when(vmRef.getId()).thenReturn(321); + + VmInfoDAO dao = new VmInfoDAOImpl(storage); + try { + dao.getVmInfo(vmRef); + fail(); + } catch (DAOException ex) { + assertEquals("Unknown VM: host:system;vm:321", ex.getMessage()); + } + + } + private Storage setupStorageForSingleVM() { Chunk query1 = new Chunk(VmInfoDAO.vmInfoCategory, false); query1.put(Key.AGENT_ID, "123");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/VMInfoCommand.java Wed May 16 15:20:08 2012 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright 2012 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.tools.cli; + +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; + +import com.redhat.thermostat.cli.ArgumentSpec; +import com.redhat.thermostat.cli.Command; +import com.redhat.thermostat.cli.CommandContext; +import com.redhat.thermostat.cli.CommandException; +import com.redhat.thermostat.cli.SimpleArgumentSpec; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.dao.DAOException; +import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmInfoDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.VmInfo; + +public class VMInfoCommand implements Command { + + private static final String NAME = "vm-info"; + private static final String DESCRIPTION = "shows basic information about a VM"; + private static final String HOST_ID_ARGUMENT = "hostId"; + private static final String VM_ID_ARGUMENT = "vmId"; + + @Override + public void run(CommandContext ctx) throws CommandException { + DAOFactory daoFactory = ApplicationContext.getInstance().getDAOFactory(); + VmInfoDAO vmsDAO = daoFactory.getVmInfoDAO(); + String hostId = ctx.getArguments().getArgument(HOST_ID_ARGUMENT); + String vmId = ctx.getArguments().getArgument(VM_ID_ARGUMENT); + HostRef host = new HostRef(hostId, "dummy"); + int parsedVmId = parseVmId(vmId); + VmRef vm = new VmRef(host, parsedVmId, "dummy"); + try { + getAndPrintVMInfo(ctx, vmsDAO, vm); + } catch (DAOException ex) { + ctx.getConsole().getError().println(ex.getMessage()); + } + } + + private int parseVmId(String vmId) throws CommandException { + try { + return Integer.parseInt(vmId); + } catch (NumberFormatException ex) { + throw new CommandException("Invalid VM ID: " + vmId, ex); + } + } + + private void getAndPrintVMInfo(CommandContext ctx, VmInfoDAO vmsDAO, VmRef vm) { + VmInfo vmInfo = vmsDAO.getVmInfo(vm); + PrintStream out = ctx.getConsole().getOutput(); + out.println("Process ID: " + vmInfo.getVmPid()); + out.println("Start time: " + new Date(vmInfo.getStartTimeStamp())); + out.println("Stop time: " + new Date(vmInfo.getStopTimeStamp())); + out.println("Main class: " + vmInfo.getMainClass()); + out.println("Command line: " + vmInfo.getJavaCommandLine()); + out.println("Java version: " + vmInfo.getJavaVersion()); + out.println("Virtual machine: " + vmInfo.getVmName()); + out.println("VM arguments: " + vmInfo.getVmArguments()); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } + + @Override + public String getUsage() { + return DESCRIPTION; + } + + @Override + public Collection<ArgumentSpec> getAcceptedArguments() { + ArgumentSpec vmId = new SimpleArgumentSpec(VM_ID_ARGUMENT, "the ID of the VM to monitor", true, true); + ArgumentSpec hostId = new SimpleArgumentSpec(HOST_ID_ARGUMENT, "the ID of the host to monitor", true, true); + return Arrays.asList(vmId, hostId); + } + + @Override + public boolean isStorageRequired() { + return true; + } + +}
--- a/tools/src/main/java/com/redhat/thermostat/tools/cli/VMListFormatter.java Tue May 15 16:09:46 2012 +0200 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/VMListFormatter.java Wed May 16 15:20:08 2012 +0200 @@ -45,6 +45,8 @@ class VMListFormatter { // TODO: Localize. + private static final String HOST_ID = "HOST_ID"; + private static final String HOST = "HOST"; private static final String VM_ID = "VM_ID"; @@ -53,11 +55,13 @@ private List<VmRef> vms = new ArrayList<>(); + private int longestHostId = HOST_ID.length(); private int longestHost = HOST.length(); private int longestVmId = VM_ID.length(); void addVM(VmRef vm) { vms.add(vm); + longestHostId = Math.max(longestHostId, vm.getAgent().getAgentId().length()); longestHost = Math.max(longestHost, vm.getAgent().getHostName().length()); longestVmId = Math.max(longestVmId, vm.getIdString().length()); } @@ -70,14 +74,16 @@ } private void printHeader(PrintStream output) { - printLine(output, HOST, VM_ID, VM_NAME); + printLine(output, HOST_ID, HOST, VM_ID, VM_NAME); } private void printVM(PrintStream output, VmRef vm) { - printLine(output, vm.getAgent().getHostName(), vm.getId().toString(), vm.getName()); + printLine(output, vm.getAgent().getAgentId(), vm.getAgent().getHostName(), vm.getId().toString(), vm.getName()); } - private void printLine(PrintStream output, String host, String vmId, String vmName) { + private void printLine(PrintStream output, String hostId, String host, String vmId, String vmName) { + output.print(hostId); + output.print(fillSpace(longestHostId - hostId.length() + 1)); output.print(host); output.print(fillSpace(longestHost - host.length() + 1)); output.print(vmId);
--- a/tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command Tue May 15 16:09:46 2012 +0200 +++ b/tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command Wed May 16 15:20:08 2012 +0200 @@ -4,3 +4,4 @@ com.redhat.thermostat.agent.AgentApplication com.redhat.thermostat.tools.cli.ListVMsCommand com.redhat.thermostat.tools.cli.ShellCommand +com.redhat.thermostat.tools.cli.VMInfoCommand
--- a/tools/src/test/java/com/redhat/thermostat/tools/cli/ListVMsCommandTest.java Tue May 15 16:09:46 2012 +0200 +++ b/tools/src/test/java/com/redhat/thermostat/tools/cli/ListVMsCommandTest.java Wed May 16 15:20:08 2012 +0200 @@ -130,8 +130,8 @@ cmd.run(ctx); String output = cmdCtxFactory.getOutput(); - assertEquals("HOST VM_ID VM_NAME\n" + - "h1 1 n\n", output); + assertEquals("HOST_ID HOST VM_ID VM_NAME\n" + + "123 h1 1 n\n", output); } @Test @@ -151,10 +151,10 @@ cmd.run(ctx); String output = cmdCtxFactory.getOutput(); - assertEquals("HOST VM_ID VM_NAME\n" + - "h1 1 n\n" + - "h1 2 n1\n" + - "longhostname 123456 longvmname\n", output); + assertEquals("HOST_ID HOST VM_ID VM_NAME\n" + + "123 h1 1 n\n" + + "123 h1 2 n1\n" + + "456 longhostname 123456 longvmname\n", output); } @Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/src/test/java/com/redhat/thermostat/tools/cli/VMInfoCommandTest.java Wed May 16 15:20:08 2012 +0200 @@ -0,0 +1,183 @@ +/* + * Copyright 2012 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.tools.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.HashMap; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.cli.AppContextSetup; +import com.redhat.thermostat.cli.ArgumentSpec; +import com.redhat.thermostat.cli.CommandContextFactory; +import com.redhat.thermostat.cli.CommandException; +import com.redhat.thermostat.cli.SimpleArgumentSpec; +import com.redhat.thermostat.cli.SimpleArguments; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; +import com.redhat.thermostat.common.dao.DAOException; +import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmInfoDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.VmInfo; +import com.redhat.thermostat.test.TestCommandContextFactory; + +public class VMInfoCommandTest { + + private VMInfoCommand cmd; + private VmInfoDAO vmsDAO; + private AppContextSetup appContextSetup; + private TestCommandContextFactory cmdCtxFactory; + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + setupCommandContextFactory(); + + cmd = new VMInfoCommand(); + + setupDAOs(); + + } + + private void setupCommandContextFactory() { + appContextSetup = mock(AppContextSetup.class); + cmdCtxFactory = new TestCommandContextFactory() { + @Override + protected AppContextSetup getAppContextSetup() { + return appContextSetup; + } + }; + CommandContextFactory.setInstance(cmdCtxFactory); + } + + private void setupDAOs() { + vmsDAO = mock(VmInfoDAO.class); + HostRef host = new HostRef("123", "dummy"); + VmRef vm = new VmRef(host, 234, "dummy"); + Calendar start = Calendar.getInstance(); + start.set(2012, 5, 7, 15, 32, 0); + Calendar end = Calendar.getInstance(); + end.set(2013, 10, 1, 1, 22, 0); + VmInfo vmInfo = new VmInfo(234, start.getTimeInMillis(), end.getTimeInMillis(), "vmVersion", "javaHome", "mainClass", "commandLine", "vmName", "vmInfo", "vmVersion", "vmArguments", new HashMap<String,String>(), new HashMap<String,String>(), new ArrayList<String>()); + when(vmsDAO.getVmInfo(vm)).thenReturn(vmInfo); + when(vmsDAO.getVmInfo(new VmRef(host, 9876, "dummy"))).thenThrow(new DAOException("Unknown VM ID: 9876")); + DAOFactory daoFactory = mock(DAOFactory.class); + when(daoFactory.getVmInfoDAO()).thenReturn(vmsDAO); + ApplicationContext.getInstance().setDAOFactory(daoFactory); + } + + + @Test + public void testVmInfo() throws CommandException { + SimpleArguments args = new SimpleArguments(); + args.addArgument("vmId", "234"); + args.addArgument("hostId", "123"); + cmd.run(cmdCtxFactory.createContext(args)); + String expected = "Process ID: 234\n" + + "Start time: Thu Jun 07 15:32:00 CEST 2012\n" + + "Stop time: Fri Nov 01 01:22:00 CET 2013\n" + + "Main class: mainClass\n" + + "Command line: commandLine\n" + + "Java version: vmVersion\n" + + "Virtual machine: vmName\n" + + "VM arguments: vmArguments\n"; + assertEquals(expected, cmdCtxFactory.getOutput()); + } + + @Test + public void testVmInfoUnknownVM() throws CommandException { + SimpleArguments args = new SimpleArguments(); + args.addArgument("vmId", "9876"); + args.addArgument("hostId", "123"); + cmd.run(cmdCtxFactory.createContext(args)); + String expected = "Unknown VM ID: 9876\n"; + assertEquals("", cmdCtxFactory.getOutput()); + assertEquals(expected, cmdCtxFactory.getError()); + } + + @Test + public void testVmInfoNonNumericalVMID() throws CommandException { + SimpleArguments args = new SimpleArguments(); + args.addArgument("vmId", "fluff"); + args.addArgument("hostId", "123"); + try { + cmd.run(cmdCtxFactory.createContext(args)); + } catch (CommandException ex) { + String expected = "Invalid VM ID: fluff"; + assertEquals(expected, ex.getMessage()); + } + } + + @Test + public void testName() { + assertEquals("vm-info", cmd.getName()); + } + + @Test + public void testDescription() { + assertEquals("shows basic information about a VM", cmd.getDescription()); + } + + @Test + public void testUsage() { + String expected = "shows basic information about a VM"; + + assertEquals(expected, cmd.getUsage()); + } + + @Test + public void testAcceptedArguments() { + Collection<ArgumentSpec> args = cmd.getAcceptedArguments(); + assertNotNull(args); + assertEquals(2, args.size()); + assertTrue(args.contains(new SimpleArgumentSpec("vmId", "the ID of the VM to monitor", true, true))); + assertTrue(args.contains(new SimpleArgumentSpec("hostId", "the ID of the host to monitor", true, true))); + } + +}