Mercurial > hg > thermostat-ng > agent
changeset 2638:6d871a711de2
Update VmInfoDAO to communicate with web gateway
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/022963.html
author | Elliott Baron <ebaron@redhat.com> |
---|---|
date | Fri, 05 May 2017 12:16:53 -0400 |
parents | 8781afc57d5e |
children | 0ed4aea0d8c2 |
files | storage/core/src/main/java/com/redhat/thermostat/storage/dao/VmInfoDAO.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOImpl.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/VmInfoTypeAdapter.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOTest.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/VmInfoTypeAdapterTest.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListener.java |
diffstat | 6 files changed, 565 insertions(+), 602 deletions(-) [+] |
line wrap: on
line diff
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/dao/VmInfoDAO.java Fri May 05 12:16:15 2017 -0400 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/dao/VmInfoDAO.java Fri May 05 12:16:53 2017 -0400 @@ -36,23 +36,18 @@ package com.redhat.thermostat.storage.dao; -import java.util.Collection; -import java.util.List; import java.util.Set; import com.redhat.thermostat.annotations.Service; import com.redhat.thermostat.storage.core.AgentId; import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.Countable; -import com.redhat.thermostat.storage.core.HostRef; import com.redhat.thermostat.storage.core.Key; import com.redhat.thermostat.storage.core.VmId; -import com.redhat.thermostat.storage.core.VmRef; import com.redhat.thermostat.storage.model.VmInfo; import com.redhat.thermostat.storage.model.VmInfo.KeyValuePair; @Service -public interface VmInfoDAO extends Countable { +public interface VmInfoDAO { static final Key<Integer> vmPidKey = new Key<>("vmPid"); static final Key<String> runtimeVersionKey = new Key<>("javaVersion"); @@ -79,28 +74,9 @@ startTimeKey, stopTimeKey, uidKey, usernameKey); - /** @return information on all known VMs */ - List<VmInfo> getAllVmInfos(); - - /** @return information on all known VMs monitored by give agent */ - List<VmInfo> getAllVmInfosForAgent(AgentId agentId); - /** @return {@code null} if no information can be found */ VmInfo getVmInfo(VmId id); - /** @return {@code null} if no information can be found */ - VmInfo getVmInfo(VmRef ref); - - /** - * - * @param host The host to get the VM(s) for. - * @return A collection of the VM(s) as VmRef(s). - * - * @deprecated use {@link #getVmIds(AgentId)} - */ - @Deprecated - Collection<VmRef> getVMs(HostRef host); - /** * * @param agentId The id of host to get the VM(s) for. @@ -110,6 +86,6 @@ void putVmInfo(VmInfo info); - void putVmStoppedTime(String vmId, long since); + void putVmStoppedTime(String agentId, String vmId, long since); }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOImpl.java Fri May 05 12:16:15 2017 -0400 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOImpl.java Fri May 05 12:16:53 2017 -0400 @@ -36,238 +36,214 @@ package com.redhat.thermostat.storage.internal.dao; -import java.util.ArrayList; -import java.util.Collection; +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; import java.util.logging.Logger; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpContentResponse; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; + import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.core.AgentId; -import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.CategoryAdapter; -import com.redhat.thermostat.storage.core.HostRef; -import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.core.PreparedStatement; -import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.VmId; -import com.redhat.thermostat.storage.core.VmRef; -import com.redhat.thermostat.storage.dao.AbstractDaoQuery; -import com.redhat.thermostat.storage.dao.AbstractDaoStatement; -import com.redhat.thermostat.storage.dao.BaseCountable; -import com.redhat.thermostat.storage.dao.SimpleDaoQuery; import com.redhat.thermostat.storage.dao.VmInfoDAO; -import com.redhat.thermostat.storage.model.AggregateCount; +import com.redhat.thermostat.storage.internal.dao.VmInfoTypeAdapter.VmInfoUpdateTypeAdapter; import com.redhat.thermostat.storage.model.VmInfo; -public class VmInfoDAOImpl extends BaseCountable implements VmInfoDAO { +public class VmInfoDAOImpl implements VmInfoDAO { private final Logger logger = LoggingUtils.getLogger(VmInfoDAOImpl.class); - static final String QUERY_VM_INFO = "QUERY " - + vmInfoCategory.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + Key.VM_ID.getName() + "' = ?s LIMIT 1"; - static final String QUERY_ALL_VMS_FOR_AGENT = "QUERY " - + vmInfoCategory.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s"; - - static final String QUERY_VM_FROM_ID = "QUERY " - + vmInfoCategory.getName() + " WHERE '" - + Key.VM_ID.getName() + "' = ?s"; + + private static final String GATEWAY_URL = "http://localhost:26000/api/v100"; // TODO configurable + private static final String GATEWAY_PATH = "/vm-info/systems/*/agents/"; + private static final String GATEWAY_PATH_JVM_SUFFIX = "/jvms/"; + private static final String CONTENT_TYPE = "application/json"; + + private final HttpHelper httpHelper; + private final JsonHelper jsonHelper; - static final String QUERY_ALL_VMS = "QUERY " + vmInfoCategory.getName(); - static final String AGGREGATE_COUNT_ALL_VMS = "QUERY-COUNT " + vmInfoCategory.getName(); - // ADD vm-info SET 'agentId' = ?s , \ - // 'vmId' = ?s , \ - // 'vmPid' = ?i , \ - // 'startTimeStamp' = ?l , \ - // 'stopTimeStamp' = ?l , \ - // 'javaVersion' = ?s , \ - // 'javaHome' = ?s , \ - // 'mainClass' = ?s , \ - // 'javaCommandLine' = ?s , \ - // 'vmName' = ?s , \ - // 'vmArguments' = ?s , \ - // 'vmInfo' = ?s , \ - // 'vmVersion' = ?s , \ - // 'propertiesAsArray' = ?p[ , \ - // 'environmentAsArray' = ?p[ , \ - // 'loadedNativeLibraries' = ?s[ , \ - // 'uid' = ?l , \ - // 'username' = ?s - static final String DESC_ADD_VM_INFO = "ADD " + vmInfoCategory.getName() + " SET " + - "'" + Key.AGENT_ID.getName() + "' = ?s , " + - "'" + Key.VM_ID.getName() + "' = ?s , " + - "'" + vmPidKey.getName() + "' = ?i , " + - "'" + startTimeKey.getName() + "' = ?l , " + - "'" + stopTimeKey.getName() + "' = ?l , " + - "'" + runtimeVersionKey.getName() + "' = ?s , " + - "'" + javaHomeKey.getName() + "' = ?s , " + - "'" + mainClassKey.getName() + "' = ?s , " + - "'" + commandLineKey.getName() + "' = ?s , " + - "'" + vmNameKey.getName() + "' = ?s , " + - "'" + vmArgumentsKey.getName() + "' = ?s , " + - "'" + vmInfoKey.getName() + "' = ?s , " + - "'" + vmVersionKey.getName() + "' = ?s , " + - "'" + propertiesKey.getName() + "' = ?p[ , " + - "'" + environmentKey.getName() + "' = ?p[ , " + - "'" + librariesKey.getName() + "' = ?s[ , " + - "'" + uidKey.getName() + "' = ?l , " + - "'" + usernameKey.getName() + "' = ?s"; - // UPDATE vm-info SET 'stopTimeStamp' = ?l WHERE 'vmId' = ?s - static final String DESC_UPDATE_VM_STOP_TIME = "UPDATE " + vmInfoCategory.getName() + - " SET '" + VmInfoDAO.stopTimeKey.getName() + "' = ?l" + - " WHERE '" + Key.VM_ID.getName() + "' = ?s"; - - private final Storage storage; - private final Category<AggregateCount> aggregateCategory; - - public VmInfoDAOImpl(Storage storage) { - this.storage = storage; - // Adapt category to the aggregate form - CategoryAdapter<VmInfo, AggregateCount> adapter = new CategoryAdapter<>(vmInfoCategory); - this.aggregateCategory = adapter.getAdapted(AggregateCount.class); - storage.registerCategory(vmInfoCategory); - storage.registerCategory(aggregateCategory); + public VmInfoDAOImpl() throws Exception { + this(new HttpHelper(new HttpClient()), new JsonHelper(new VmInfoTypeAdapter(), new VmInfoUpdateTypeAdapter())); } - @Override - public List<VmInfo> getAllVmInfos() { - return executeQuery(new SimpleDaoQuery<>(storage, vmInfoCategory, QUERY_ALL_VMS)).asList(); + VmInfoDAOImpl(HttpHelper httpHelper, JsonHelper jsonHelper) throws Exception { + this.jsonHelper = jsonHelper; + this.httpHelper = httpHelper; + + this.httpHelper.startClient(); } @Override public VmInfo getVmInfo(final VmId id) { - return executeQuery( - new AbstractDaoQuery<VmInfo>(storage, vmInfoCategory, QUERY_VM_FROM_ID) { - @Override - public PreparedStatement<VmInfo> customize(PreparedStatement<VmInfo> preparedStatement) { - preparedStatement.setString(0, id.get()); - return preparedStatement; - } - }).head(); - } - - @Override - public VmInfo getVmInfo(final VmRef ref) { - return executeQuery( - new AbstractDaoQuery<VmInfo>(storage, vmInfoCategory, QUERY_VM_INFO) { - @Override - public PreparedStatement<VmInfo> customize(PreparedStatement<VmInfo> preparedStatement) { - preparedStatement.setString(0, ref.getHostRef().getAgentId()); - preparedStatement.setString(1, ref.getVmId()); - return preparedStatement; - } - }).head(); - } - - @Override - public Collection<VmRef> getVMs(HostRef host) { - AgentId agentId = new AgentId(host.getAgentId()); - - Collection<VmInfo> vmInfos = getAllVmInfosForAgent(agentId); - if (vmInfos.equals(Collections.emptyList())) { - return Collections.emptyList(); - } - - return buildVMsFromQuery(vmInfos, host); - } - - @Deprecated - private Collection<VmRef> buildVMsFromQuery(Collection<VmInfo> vmInfos, HostRef host) { - List<VmRef> vmRefs = new ArrayList<>(); - for (VmInfo vmInfo : vmInfos) { - VmRef vm = buildVmRefFromChunk(vmInfo, host); - vmRefs.add(vm); - } - - return vmRefs; - } - - @Deprecated - private VmRef buildVmRefFromChunk(VmInfo vmInfo, HostRef host) { - String id = vmInfo.getVmId(); - Integer pid = vmInfo.getVmPid(); - // TODO can we do better than the main class? - String mainClass = vmInfo.getMainClass(); - return new VmRef(host, id, pid, mainClass); + return null; // TODO Remove once VM Id completer is removed } @Override public Set<VmId> getVmIds(AgentId agentId) { - Set<VmId> vmIds = new HashSet<>(); - Collection<VmInfo> vmInfos = getAllVmInfosForAgent(agentId); - for (VmInfo vmInfo : vmInfos) { - vmIds.add(new VmId(vmInfo.getVmId())); - } - - return vmIds; - } - - @Override - public List<VmInfo> getAllVmInfosForAgent(final AgentId agentId) { - return executeQuery( - new AbstractDaoQuery<VmInfo>(storage, vmInfoCategory, QUERY_ALL_VMS_FOR_AGENT) { - @Override - public PreparedStatement<VmInfo> customize(PreparedStatement<VmInfo> preparedStatement) { - preparedStatement.setString(0, agentId.get()); - return preparedStatement; - } - }).asList(); - } - - @Override - public long getCount() { - return getCount(storage, aggregateCategory, AGGREGATE_COUNT_ALL_VMS); + return Collections.emptySet(); // TODO Remove once VM Id completer is removed } @Override public void putVmInfo(final VmInfo info) { - executeStatement( - new AbstractDaoStatement<VmInfo>(storage, vmInfoCategory, DESC_ADD_VM_INFO) { - @Override - public PreparedStatement<VmInfo> customize(PreparedStatement<VmInfo> preparedStatement) { - preparedStatement.setString(0, info.getAgentId()); - preparedStatement.setString(1, info.getVmId()); - preparedStatement.setInt(2, info.getVmPid()); - preparedStatement.setLong(3, info.getStartTimeStamp()); - preparedStatement.setLong(4, info.getStopTimeStamp()); - preparedStatement.setString(5, info.getJavaVersion()); - preparedStatement.setString(6, info.getJavaHome()); - preparedStatement.setString(7, info.getMainClass()); - preparedStatement.setString(8, info.getJavaCommandLine()); - preparedStatement.setString(9, info.getVmName()); - preparedStatement.setString(10, info.getVmArguments()); - preparedStatement.setString(11, info.getVmInfo()); - preparedStatement.setString(12, info.getVmVersion()); - preparedStatement.setPojoList(13, info.getPropertiesAsArray()); - preparedStatement.setPojoList(14, info.getEnvironmentAsArray()); - preparedStatement.setStringList(15, info.getLoadedNativeLibraries()); - preparedStatement.setLong(16, info.getUid()); - preparedStatement.setString(17, info.getUsername()); - return preparedStatement; - } - }); + try { + // Encode as JSON and send as POST request + String json = jsonHelper.toJson(Arrays.asList(info)); + StringContentProvider provider = httpHelper.createContentProvider(json); + + String url = getAddURL(info.getAgentId()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.POST); + httpRequest.content(provider, CONTENT_TYPE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to send JVM information to web gateway", e); + } } @Override - public void putVmStoppedTime(final String vmId, final long timestamp) { - executeStatement( - new AbstractDaoStatement<VmInfo>(storage, vmInfoCategory, DESC_UPDATE_VM_STOP_TIME) { - @Override - public PreparedStatement<VmInfo> customize(PreparedStatement<VmInfo> preparedStatement) { - preparedStatement.setLong(0, timestamp); - preparedStatement.setString(1, vmId); - return preparedStatement; - } - }); + public void putVmStoppedTime(final String agentId, final String vmId, final long timestamp) { + try { + // Encode as JSON and send as PUT request + VmInfoUpdate update = new VmInfoUpdate(timestamp); + String json = jsonHelper.toJson(update); + StringContentProvider provider = httpHelper.createContentProvider(json); + + String url = getUpdateURL(agentId, vmId); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.PUT); + httpRequest.content(provider, CONTENT_TYPE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to send JVM information update to web gateway", e); + } + } + + private void sendRequest(Request httpRequest) + throws InterruptedException, TimeoutException, ExecutionException, IOException { + ContentResponse resp = httpRequest.send(); + int status = resp.getStatus(); + if (status != HttpStatus.OK_200) { + throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason()); + } + } + + private String getAddURL(String agentId) { + StringBuilder builder = buildURL(agentId); + return builder.toString(); } - @Override - protected Logger getLogger() { - return logger; + private StringBuilder buildURL(String agentId) { + StringBuilder builder = new StringBuilder(); + builder.append(GATEWAY_URL); + builder.append(GATEWAY_PATH); + builder.append(agentId); + return builder; + } + + private String getUpdateURL(String agentId, String vmId) { + StringBuilder builder = buildURL(agentId); + builder.append(GATEWAY_PATH_JVM_SUFFIX); + builder.append(vmId); + return builder.toString(); + } + + static class VmInfoUpdate { + + private final long stoppedTime; + + VmInfoUpdate(long stoppedTime) { + this.stoppedTime = stoppedTime; + } + + long getStoppedTime() { + return stoppedTime; + } + } + + + // For testing purposes + static class JsonHelper { + + private final VmInfoTypeAdapter typeAdapter; + private final VmInfoUpdateTypeAdapter updateTypeAdapter; + + public JsonHelper(VmInfoTypeAdapter typeAdapter, VmInfoUpdateTypeAdapter updateTypeAdapter) { + this.typeAdapter = typeAdapter; + this.updateTypeAdapter = updateTypeAdapter; + } + + String toJson(List<VmInfo> infos) throws IOException { + return typeAdapter.toJson(infos); + } + + String toJson(VmInfoUpdate update) throws IOException { + return updateTypeAdapter.toJson(update); + } + + } + + // For testing purposes + static class HttpHelper { + + private final HttpClient httpClient; + + HttpHelper(HttpClient httpClient) { + this.httpClient = httpClient; + } + + void startClient() throws Exception { + httpClient.start(); + } + + StringContentProvider createContentProvider(String content) { + return new StringContentProvider(content); + } + + Request newRequest(String url) { + return new MockRequest(httpClient, URI.create(url)); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockRequest extends HttpRequest { + + MockRequest(HttpClient client, URI uri) { + super(client, uri); + } + + @Override + public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException { + return new MockResponse(); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockResponse extends HttpContentResponse { + + MockResponse() { + super(null, null, null); + } + + @Override + public int getStatus() { + return HttpStatus.OK_200; + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/VmInfoTypeAdapter.java Fri May 05 12:16:53 2017 -0400 @@ -0,0 +1,198 @@ +/* + * Copyright 2012-2017 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.storage.internal.dao; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl.VmInfoUpdate; +import com.redhat.thermostat.storage.model.VmInfo; + +public class VmInfoTypeAdapter extends TypeAdapter<List<VmInfo>> { + + private static final String AGENT_ID = "agentId"; + private static final String VM_ID = "vmId"; + private static final String VM_PID = "vmPid"; + private static final String JAVA_VERSION = "javaVersion"; + private static final String JAVA_HOME = "javaHome"; + private static final String MAIN_CLASS = "mainClass"; + private static final String JAVA_COMMAND_LINE = "javaCommandLine"; + private static final String VM_ARGUMENTS = "vmArguments"; + private static final String VM_NAME = "vmName"; + private static final String VM_INFO = "vmInfo"; + private static final String VM_VERSION = "vmVersion"; + private static final String PROPERTIES_AS_ARRAY = "propertiesAsArray"; + private static final String ENVIRONMENT_AS_ARRAY = "environmentAsArray"; + private static final String LOADED_NATIVE_LIBRARIES = "loadedNativeLibraries"; + private static final String START_TIME_STAMP = "startTimeStamp"; + private static final String STOP_TIME_STAMP = "stopTimeStamp"; + private static final String UID = "uid"; + private static final String USERNAME = "username"; + private static final String TYPE_LONG = "$numberLong"; + private static final String KEY = "key"; + private static final String VALUE = "value"; + + @Override + public void write(JsonWriter out, List<VmInfo> value) throws IOException { + // Request is an array of VmInfo objects + out.beginArray(); + + for (VmInfo info : value) { + writeVmInfo(out, info); + } + + out.endArray(); + } + + private void writeVmInfo(JsonWriter out, VmInfo info) throws IOException { + out.beginObject(); + + // Write each field of VmInfo as part of a JSON object + out.name(AGENT_ID); + out.value(info.getAgentId()); + out.name(VM_ID); + out.value(info.getVmId()); + out.name(VM_PID); + out.value(info.getVmPid()); + out.name(START_TIME_STAMP); + writeLong(out, info.getStartTimeStamp()); + out.name(STOP_TIME_STAMP); + writeLong(out, info.getStopTimeStamp()); + out.name(JAVA_VERSION); + out.value(info.getJavaVersion()); + out.name(JAVA_HOME); + out.value(info.getJavaHome()); + out.name(MAIN_CLASS); + out.value(info.getMainClass()); + out.name(JAVA_COMMAND_LINE); + out.value(info.getJavaCommandLine()); + out.name(VM_NAME); + out.value(info.getVmName()); + out.name(VM_ARGUMENTS); + out.value(info.getVmArguments()); + out.name(VM_INFO); + out.value(info.getVmInfo()); + out.name(VM_VERSION); + out.value(info.getVmVersion()); + out.name(PROPERTIES_AS_ARRAY); + writeStringMap(out, info.getProperties()); + out.name(ENVIRONMENT_AS_ARRAY); + writeStringMap(out, info.getEnvironment()); + out.name(LOADED_NATIVE_LIBRARIES); + writeStringArray(out, info.getLoadedNativeLibraries()); + out.name(UID); + writeLong(out, info.getUid()); + out.name(USERNAME); + out.value(info.getUsername()); + + out.endObject(); + } + + private void writeStringMap(JsonWriter out, Map<String, String> map) throws IOException { + // Write contents of Map as an array of JSON objects + out.beginArray(); + + Set<Entry<String, String>> entries = map.entrySet(); + for (Map.Entry<String, String> entry : entries) { + // Create JSON object with key and value labeled as JSON names + out.beginObject(); + out.name(KEY); + out.value(entry.getKey()); + out.name(VALUE); + out.value(entry.getValue()); + out.endObject(); + } + + out.endArray(); + } + + private void writeStringArray(JsonWriter out, String[] array) throws IOException { + // Write String[] as JSON array + out.beginArray(); + + for (String item : array) { + out.value(item); + } + + out.endArray(); + } + + private static void writeLong(JsonWriter out, long value) throws IOException { + // Write MongoDB representation of a Long + out.beginObject(); + out.name(TYPE_LONG); + out.value(String.valueOf(value)); + out.endObject(); + } + + @Override + public List<VmInfo> read(JsonReader in) throws IOException { + throw new UnsupportedOperationException(); + } + + static class VmInfoUpdateTypeAdapter extends TypeAdapter<VmInfoUpdate> { + + private static final String SET = "set"; + + @Override + public void write(JsonWriter out, VmInfoUpdate value) throws IOException { + // List fields to update as part of a JSON object with name "set" + out.beginObject(); + out.name(SET); + + out.beginObject(); + out.name(STOP_TIME_STAMP); + writeLong(out, value.getStoppedTime()); + out.endObject(); + + out.endObject(); + } + + @Override + public VmInfoUpdate read(JsonReader in) throws IOException { + throw new UnsupportedOperationException(); + } + + } + +}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOTest.java Fri May 05 12:16:15 2017 -0400 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/VmInfoDAOTest.java Fri May 05 12:16:53 2017 -0400 @@ -37,117 +37,90 @@ package com.redhat.thermostat.storage.internal.dao; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import com.redhat.thermostat.storage.core.AgentId; -import com.redhat.thermostat.storage.core.Cursor; -import com.redhat.thermostat.storage.core.DescriptorParsingException; -import com.redhat.thermostat.storage.core.HostRef; import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.core.PreparedStatement; -import com.redhat.thermostat.storage.core.StatementDescriptor; -import com.redhat.thermostat.storage.core.StatementExecutionException; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.core.VmId; -import com.redhat.thermostat.storage.core.VmRef; import com.redhat.thermostat.storage.dao.VmInfoDAO; -import com.redhat.thermostat.storage.model.AggregateCount; +import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl.HttpHelper; +import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl.JsonHelper; +import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl.VmInfoUpdate; import com.redhat.thermostat.storage.model.VmInfo; import com.redhat.thermostat.storage.model.VmInfo.KeyValuePair; public class VmInfoDAOTest { - private String vmId; - private int vmPid; - private long startTime; - private long stopTime; - private String jVersion; - private String jHome; - private String mainClass; - private String commandLine; - private String vmName; - private String vmInfo; - private String vmVersion; - private String vmArgs; - private Map<String, String> props; - private Map<String, String> env; - private String[] libs; - private long uid; - private String username; + private static final String URL = "http://localhost:26000/api/v100/vm-info/systems/*/agents/foo-agent"; + private static final String UPDATE_URL = URL + "/jvms/vmId"; + private static final String SOME_JSON = "{\"some\" : \"json\"}"; + private static final String SOME_OTHER_JSON = "{\"some\" : {\"other\" : \"json\"}}"; + private static final String CONTENT_TYPE = "application/json"; + + private VmInfo info; + private JsonHelper jsonHelper; + private HttpHelper httpHelper; + private StringContentProvider contentProvider; + private Request request; + private ContentResponse response; @Before - public void setUp() { - vmId = "vmId"; - vmPid = 1; - startTime = 2; - stopTime = 3; - jVersion = "java 1.0"; - jHome = "/path/to/jdk/home"; - mainClass = "Hello.class"; - commandLine = "World"; - vmArgs = "-XX=+FastestJITPossible"; - vmName = "Hotspot"; - vmInfo = "Some info"; - vmVersion = "1.0"; - props = new HashMap<>(); - env = new HashMap<>(); - libs = new String[0]; - uid = 2000; - username = "myUser"; + public void setUp() throws Exception { + String vmId = "vmId"; + int vmPid = 1; + long startTime = 2L; + long stopTime = Long.MIN_VALUE; + String jVersion = "java 1.0"; + String jHome = "/path/to/jdk/home"; + String mainClass = "Hello.class"; + String commandLine = "World"; + String vmArgs = "-XX=+FastestJITPossible"; + String vmName = "Hotspot"; + String vmInfo = "Some info"; + String vmVersion = "1.0"; + Map<String, String> props = new HashMap<>(); + Map<String, String> env = new HashMap<>(); + String[] libs = new String[0]; + long uid = 2000L; + String username = "myUser"; + info = new VmInfo("foo-agent", vmId, vmPid, startTime, stopTime, jVersion, jHome, + mainClass, commandLine, vmName, vmInfo, vmVersion, vmArgs, + props, env, libs, uid, username); + + httpHelper = mock(HttpHelper.class); + contentProvider = mock(StringContentProvider.class); + when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider); + request = mock(Request.class); + when(httpHelper.newRequest(anyString())).thenReturn(request); + response = mock(ContentResponse.class); + when(response.getStatus()).thenReturn(HttpStatus.OK_200); + when(request.send()).thenReturn(response); + + jsonHelper = mock(JsonHelper.class); + when(jsonHelper.toJson(anyListOf(VmInfo.class))).thenReturn(SOME_JSON); + when(jsonHelper.toJson(any(VmInfoUpdate.class))).thenReturn(SOME_OTHER_JSON); } @Test - public void preparedQueryDescriptorsAreSane() { - String expectedVmInfo = "QUERY vm-info WHERE 'agentId' = ?s AND 'vmId' = ?s LIMIT 1"; - assertEquals(expectedVmInfo, VmInfoDAOImpl.QUERY_VM_INFO); - String expectedVmInfoAll = "QUERY vm-info WHERE 'agentId' = ?s"; - assertEquals(expectedVmInfoAll, VmInfoDAOImpl.QUERY_ALL_VMS_FOR_AGENT); - String expectedAllVms = "QUERY vm-info"; - assertEquals(expectedAllVms, VmInfoDAOImpl.QUERY_ALL_VMS); - String aggregateAllVms = "QUERY-COUNT vm-info"; - assertEquals(aggregateAllVms, VmInfoDAOImpl.AGGREGATE_COUNT_ALL_VMS); - String addVmInfo = "ADD vm-info SET 'agentId' = ?s , " + - "'vmId' = ?s , " + - "'vmPid' = ?i , " + - "'startTimeStamp' = ?l , " + - "'stopTimeStamp' = ?l , " + - "'javaVersion' = ?s , " + - "'javaHome' = ?s , " + - "'mainClass' = ?s , " + - "'javaCommandLine' = ?s , " + - "'vmName' = ?s , " + - "'vmArguments' = ?s , " + - "'vmInfo' = ?s , " + - "'vmVersion' = ?s , " + - "'propertiesAsArray' = ?p[ , " + - "'environmentAsArray' = ?p[ , " + - "'loadedNativeLibraries' = ?s[ , " + - "'uid' = ?l , " + - "'username' = ?s"; - assertEquals(addVmInfo, VmInfoDAOImpl.DESC_ADD_VM_INFO); - String updateVmStopTime = "UPDATE vm-info SET 'stopTimeStamp' = ?l WHERE 'vmId' = ?s"; - assertEquals(updateVmStopTime, VmInfoDAOImpl.DESC_UPDATE_VM_STOP_TIME); - } - - @Test public void testCategory() { assertEquals("vm-info", VmInfoDAO.vmInfoCategory.getName()); Collection<Key<?>> keys = VmInfoDAO.vmInfoCategory.getKeys(); @@ -173,303 +146,36 @@ } @Test - public void testGetVMsDescriptorException() throws DescriptorParsingException { - Storage storage = mock(Storage.class); - VmInfoDAO vmInfoDao = new VmInfoDAOImpl(storage); - HostRef host = new HostRef("123", "fluffhost"); - - when(storage.prepareStatement(anyDescriptor())).thenThrow(new DescriptorParsingException("testException")); - - Collection<VmRef> vmRefs = vmInfoDao.getVMs(host); - assertEquals(Collections.emptyList(), vmRefs); - } - - @Test - public void testGetVmIdsDescriptorException() throws DescriptorParsingException { - Storage storage = mock(Storage.class); - VmInfoDAO vmInfoDao = new VmInfoDAOImpl(storage); - AgentId agentId = new AgentId("agentId"); - - when(storage.prepareStatement(anyDescriptor())).thenThrow(new DescriptorParsingException("testException")); - - Set<VmId> vmIds = vmInfoDao.getVmIds(agentId); - assertEquals(Collections.emptySet(), vmIds); - } - - @Test - public void testGetVmInfo() throws DescriptorParsingException, StatementExecutionException { - Storage storage = mock(Storage.class); - @SuppressWarnings("unchecked") - PreparedStatement<VmInfo> stmt = (PreparedStatement<VmInfo>) mock(PreparedStatement.class); - when(storage.prepareStatement(anyDescriptor())).thenReturn(stmt); - VmInfo expected = new VmInfo("foo-agent", vmId, vmPid, startTime, stopTime, jVersion, jHome, mainClass, commandLine, vmName, vmInfo, vmVersion, vmArgs, props, env, libs, uid, username); - @SuppressWarnings("unchecked") - Cursor<VmInfo> cursor = (Cursor<VmInfo>) mock(Cursor.class); - when(cursor.hasNext()).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(expected).thenReturn(null); - when(stmt.executeQuery()).thenReturn(cursor); - - HostRef hostRef = mock(HostRef.class); - when(hostRef.getAgentId()).thenReturn("system"); - - VmRef vmRef = mock(VmRef.class); - when(vmRef.getHostRef()).thenReturn(hostRef); - when(vmRef.getVmId()).thenReturn("vmId"); - - VmInfoDAO dao = new VmInfoDAOImpl(storage); - VmInfo info = dao.getVmInfo(vmRef); - assertEquals(expected, info); - - verify(storage).prepareStatement(anyDescriptor()); - verify(stmt).setString(0, "system"); - verify(stmt).setString(1, "vmId"); - verify(stmt).executeQuery(); - } - - @SuppressWarnings("unchecked") - private StatementDescriptor<VmInfo> anyDescriptor() { - return (StatementDescriptor<VmInfo>) any(StatementDescriptor.class); - } - - @Test - public void testGetVmInfoUnknownVM() throws DescriptorParsingException, StatementExecutionException { - Storage storage = mock(Storage.class); - @SuppressWarnings("unchecked") - PreparedStatement<VmInfo> stmt = (PreparedStatement<VmInfo>) mock(PreparedStatement.class); - when(storage.prepareStatement(anyDescriptor())).thenReturn(stmt); - @SuppressWarnings("unchecked") - Cursor<VmInfo> cursor = (Cursor<VmInfo>) mock(Cursor.class); - when(stmt.executeQuery()).thenReturn(cursor); + public void testPutVmInfo() throws Exception { + VmInfoDAO dao = new VmInfoDAOImpl(httpHelper, jsonHelper); + dao.putVmInfo(info); - HostRef hostRef = mock(HostRef.class); - when(hostRef.getAgentId()).thenReturn("system"); - - VmRef vmRef = mock(VmRef.class); - when(vmRef.getVmId()).thenReturn("noVm"); - when(vmRef.getHostRef()).thenReturn(hostRef); - - VmInfoDAO dao = new VmInfoDAOImpl(storage); - VmInfo result = dao.getVmInfo(vmRef); - - assertNull(result); - - verify(storage).prepareStatement(anyDescriptor()); - verify(stmt).setString(0, "system"); - verify(stmt).setString(1, "noVm"); - verify(stmt).executeQuery(); - } - - @Test - public void testGetVMsWithSingleVM() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForSingleVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - HostRef host = new HostRef("123", "fluffhost"); - - Collection<VmRef> vms = dao.getVMs(host); - - assertVmRefCollection(vms, new VmRef(host, "vmId", 123, "mainClass1")); - } - - @Test - public void testGetVmIdsWithSingleVM() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForSingleVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - AgentId agentId = new AgentId("123"); - - Set<VmId> vmIds = dao.getVmIds(agentId); - - assertVmIdCollection(vmIds, new VmId("vmId")); - } - - private Storage setupStorageForSingleVM() throws DescriptorParsingException, StatementExecutionException { - - VmInfo vm1 = new VmInfo(); - vm1.setVmId("vmId"); - vm1.setVmPid(123); - vm1.setMainClass("mainClass1"); - - @SuppressWarnings("unchecked") - Cursor<VmInfo> singleVMCursor = (Cursor<VmInfo>) mock(Cursor.class); - when(singleVMCursor.hasNext()).thenReturn(true).thenReturn(false); - when(singleVMCursor.next()).thenReturn(vm1); - - Storage storage = mock(Storage.class); - @SuppressWarnings("unchecked") - PreparedStatement<VmInfo> stmt = (PreparedStatement<VmInfo>) mock(PreparedStatement.class); - when(storage.prepareStatement(anyDescriptor())).thenReturn(stmt); - when(stmt.executeQuery()).thenReturn(singleVMCursor); - return storage; - } - - @Test - public void testGetVMsWithMultiVMs() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForMultiVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - HostRef host = new HostRef("456", "fluffhost"); - - Collection<VmRef> vms = dao.getVMs(host); - - assertVmRefCollection(vms, new VmRef(host, "vmId1", 123, "mainClass1"), new VmRef(host, "vmId2", 456, "mainClass2")); + verify(httpHelper).newRequest(URL); + verify(request).method(HttpMethod.POST); + verify(jsonHelper).toJson(eq(Arrays.asList(info))); + verify(httpHelper).createContentProvider(SOME_JSON); + verify(request).content(contentProvider, CONTENT_TYPE); + verify(request).send(); + verify(response).getStatus(); } @Test - public void testGetVmIdsWithMultiVMs() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForMultiVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - AgentId agentId = new AgentId("456"); - - Set<VmId> vmIds = dao.getVmIds(agentId); - - assertVmIdCollection(vmIds, new VmId("vmId1"), new VmId("vmId2")); - } - - - @Test - public void testGetAllVmInfos() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForMultiVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - - List<VmInfo> vmInfos = dao.getAllVmInfos(); - - assertTrue(vmInfos.size() == 2); - } - - @Test - public void testGetAllVmInfosForAgent() throws DescriptorParsingException, StatementExecutionException { - Storage storage = setupStorageForMultiVM(); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - AgentId agentId = new AgentId("456"); - - List<VmInfo> vmInfos = dao.getAllVmInfosForAgent(agentId); - - assertTrue(vmInfos.size() == 2); - } - - private Storage setupStorageForMultiVM() throws DescriptorParsingException, StatementExecutionException { - VmInfo vm1 = new VmInfo(); - vm1.setVmId("vmId1"); - vm1.setVmPid(123); - vm1.setMainClass("mainClass1"); - - VmInfo vm2 = new VmInfo(); - vm2.setVmId("vmId2"); - vm2.setVmPid(456); - vm2.setMainClass("mainClass2"); - - @SuppressWarnings("unchecked") - Cursor<VmInfo> multiVMsCursor = mock(Cursor.class); - when(multiVMsCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); - when(multiVMsCursor.next()).thenReturn(vm1).thenReturn(vm2); - - Storage storage = mock(Storage.class); - @SuppressWarnings("unchecked") - PreparedStatement<VmInfo> stmt = (PreparedStatement<VmInfo>) mock(PreparedStatement.class); - when(storage.prepareStatement(anyDescriptor())).thenReturn(stmt); - when(stmt.executeQuery()).thenReturn(multiVMsCursor); - return storage; - } - - private void assertVmRefCollection(Collection<VmRef> vms, VmRef... expectedVMs) { - assertEquals(expectedVMs.length, vms.size()); - for (VmRef expectedVM : expectedVMs) { - assertTrue(vms.contains(expectedVM)); - } - } - - private void assertVmIdCollection(Collection<VmId> vms, VmId... expectedVmIds) { - assertEquals(expectedVmIds.length, vms.size()); - for (VmId expectedVmId : expectedVmIds) { - assertTrue(vms.contains(expectedVmId)); - } - } - - @Test - public void testGetCount() - throws DescriptorParsingException, StatementExecutionException { - AggregateCount count = new AggregateCount(); - count.setCount(2); + public void testPutVmStoppedTime() throws Exception { + VmInfoDAO dao = new VmInfoDAOImpl(httpHelper, jsonHelper); + dao.putVmStoppedTime("foo-agent", "vmId", 3L); - @SuppressWarnings("unchecked") - Cursor<AggregateCount> c = (Cursor<AggregateCount>) mock(Cursor.class); - when(c.hasNext()).thenReturn(true).thenReturn(false); - when(c.next()).thenReturn(count).thenThrow(new NoSuchElementException()); - - Storage storage = mock(Storage.class); - @SuppressWarnings("unchecked") - PreparedStatement<AggregateCount> stmt = (PreparedStatement<AggregateCount>) mock(PreparedStatement.class); - @SuppressWarnings("unchecked") - StatementDescriptor<AggregateCount> desc = any(StatementDescriptor.class); - when(storage.prepareStatement(desc)).thenReturn(stmt); - when(stmt.executeQuery()).thenReturn(c); - VmInfoDAOImpl dao = new VmInfoDAOImpl(storage); - - assertEquals(2, dao.getCount()); - } - - @SuppressWarnings("unchecked") - @Test - public void testPutVmInfo() throws DescriptorParsingException, StatementExecutionException { - Storage storage = mock(Storage.class); - PreparedStatement<VmInfo> add = mock(PreparedStatement.class); - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(add); - - VmInfo info = new VmInfo("foo-agent", vmId, vmPid, startTime, stopTime, jVersion, jHome, - mainClass, commandLine, vmName, vmInfo, vmVersion, vmArgs, - props, env, libs, uid, username); - VmInfoDAO dao = new VmInfoDAOImpl(storage); - dao.putVmInfo(info); - - @SuppressWarnings("rawtypes") - ArgumentCaptor<StatementDescriptor> captor = ArgumentCaptor.forClass(StatementDescriptor.class); + verify(httpHelper).newRequest(UPDATE_URL); + verify(request).method(HttpMethod.PUT); - verify(storage).prepareStatement(captor.capture()); - StatementDescriptor<?> desc = captor.getValue(); - assertEquals(VmInfoDAOImpl.DESC_ADD_VM_INFO, desc.getDescriptor()); - - verify(add).setString(0, info.getAgentId()); - verify(add).setString(1, info.getVmId()); - verify(add).setInt(2, info.getVmPid()); - verify(add).setLong(3, info.getStartTimeStamp()); - verify(add).setLong(4, info.getStopTimeStamp()); - verify(add).setString(5, info.getJavaVersion()); - verify(add).setString(6, info.getJavaHome()); - verify(add).setString(7, info.getMainClass()); - verify(add).setString(8, info.getJavaCommandLine()); - verify(add).setString(9, info.getVmName()); - verify(add).setString(10, info.getVmArguments()); - verify(add).setString(11, info.getVmInfo()); - verify(add).setString(12, info.getVmVersion()); - verify(add).setPojoList(13, info.getPropertiesAsArray()); - verify(add).setPojoList(14, info.getEnvironmentAsArray()); - verify(add).setStringList(15, info.getLoadedNativeLibraries()); - verify(add).setLong(16, info.getUid()); - verify(add).setString(17, info.getUsername()); - verify(add).execute(); - verifyNoMoreInteractions(add); - } - - @SuppressWarnings("unchecked") - @Test - public void testPutVmStoppedTime() throws DescriptorParsingException, - StatementExecutionException { - Storage storage = mock(Storage.class); - PreparedStatement<VmInfo> update = mock(PreparedStatement.class); - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(update); - - VmInfoDAO dao = new VmInfoDAOImpl(storage); - dao.putVmStoppedTime(vmId, stopTime); - - @SuppressWarnings("rawtypes") - ArgumentCaptor<StatementDescriptor> captor = ArgumentCaptor.forClass(StatementDescriptor.class); - - verify(storage).prepareStatement(captor.capture()); - StatementDescriptor<?> desc = captor.getValue(); - assertEquals(VmInfoDAOImpl.DESC_UPDATE_VM_STOP_TIME, desc.getDescriptor()); - - verify(update).setLong(0, stopTime); - verify(update).setString(1, vmId); - verify(update).execute(); - verifyNoMoreInteractions(update); + ArgumentCaptor<VmInfoUpdate> updateCaptor = ArgumentCaptor.forClass(VmInfoUpdate.class); + verify(jsonHelper).toJson(updateCaptor.capture()); + VmInfoUpdate update = updateCaptor.getValue(); + assertEquals(3L, update.getStoppedTime()); + + verify(httpHelper).createContentProvider(SOME_OTHER_JSON); + verify(request).content(contentProvider, CONTENT_TYPE); + verify(request).send(); + verify(response).getStatus(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/VmInfoTypeAdapterTest.java Fri May 05 12:16:53 2017 -0400 @@ -0,0 +1,107 @@ +/* + * Copyright 2012-2017 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.storage.internal.dao; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl.VmInfoUpdate; +import com.redhat.thermostat.storage.internal.dao.VmInfoTypeAdapter.VmInfoUpdateTypeAdapter; +import com.redhat.thermostat.storage.model.VmInfo; + +public class VmInfoTypeAdapterTest { + + @Test + public void testWrite() throws Exception { + VmInfoTypeAdapter adapter = new VmInfoTypeAdapter(); + final String expected = "[{\"agentId\":\"agent1\",\"vmId\":\"vm1\",\"vmPid\":8000," + + "\"startTimeStamp\":{\"$numberLong\":\"50000\"},\"stopTimeStamp\":" + + "{\"$numberLong\":\"-9223372036854775808\"},\"javaVersion\":\"1.8.0\"," + + "\"javaHome\":\"/path/to/java\",\"mainClass\":\"myClass\",\"javaCommandLine\":\"java myClass\"," + + "\"vmName\":\"myJVM\",\"vmArguments\":\"-Dhello\",\"vmInfo\":\"interesting\"," + + "\"vmVersion\":\"1800\",\"propertiesAsArray\":[{\"key\":\"A\",\"value\":\"B\"}," + + "{\"key\":\"C\",\"value\":\"D\"}],\"environmentAsArray\":[{\"key\":\"E\",\"value\":\"F\"}," + + "{\"key\":\"G\",\"value\":\"H\"}],\"loadedNativeLibraries\":[],\"uid\":{\"$numberLong\":\"1234\"}," + + "\"username\":\"test\"}," + + "{\"agentId\":\"agent2\",\"vmId\":\"vm2\",\"vmPid\":9000,\"startTimeStamp\":" + + "{\"$numberLong\":\"100000\"},\"stopTimeStamp\":{\"$numberLong\":\"200000\"}," + + "\"javaVersion\":\"1.7.0\",\"javaHome\":\"/path/to/jre\",\"mainClass\":\"myOtherClass\"," + + "\"javaCommandLine\":\"otherClass.sh\",\"vmName\":\"myOtherJVM\",\"vmArguments\":\"-Dworld\"," + + "\"vmInfo\":\"info\",\"vmVersion\":\"1700\",\"propertiesAsArray\":[],\"environmentAsArray\":" + + "[{\"key\":\"A\",\"value\":\"B\"},{\"key\":\"C\",\"value\":\"D\"}]," + + "\"loadedNativeLibraries\":[\"libhello\",\"libworld\"],\"uid\":{\"$numberLong\":\"5678\"}" + + ",\"username\":\"user\"}]"; + + final Map<String, String> props = new HashMap<>(); + props.put("A", "B"); + props.put("C", "D"); + final Map<String, String> env = new HashMap<>(); + env.put("E", "F"); + env.put("G", "H"); + VmInfo first = new VmInfo("agent1", "vm1", 8000, 50000L, Long.MIN_VALUE, "1.8.0", "/path/to/java", "myClass", + "java myClass", "myJVM", "interesting", "1800", "-Dhello", props, env, new String[0], 1234L, "test"); + + final Map<String, String> props2 = new HashMap<>(); + final Map<String, String> env2 = new HashMap<>(); + env2.put("A", "B"); + env2.put("C", "D"); + final String[] libs = { "libhello", "libworld" }; + VmInfo second = new VmInfo("agent2", "vm2", 9000, 100000L, 200000L, "1.7.0", "/path/to/jre", "myOtherClass", + "otherClass.sh", "myOtherJVM", "info", "1700", "-Dworld", props2, env2, libs, 5678L, "user"); + List<VmInfo> infos = Arrays.asList(first, second); + + String json = adapter.toJson(infos); + assertEquals(expected, json); + } + + @Test + public void testUpdate() throws Exception { + VmInfoUpdateTypeAdapter adapter = new VmInfoUpdateTypeAdapter(); + final String expected = "{\"set\":{\"stopTimeStamp\":{\"$numberLong\":\"5000\"}}}"; + + VmInfoUpdate update = new VmInfoUpdate(5000L); + String json = adapter.toJson(update); + assertEquals(expected, json); + } + +}
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListener.java Fri May 05 12:16:15 2017 -0400 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListener.java Fri May 05 12:16:53 2017 -0400 @@ -171,7 +171,7 @@ notifier.notifyVmStatusChange(Status.VM_STOPPED, vmId, vmPid); long stopTime = System.currentTimeMillis(); - vmInfoDAO.putVmStoppedTime(vmId, stopTime); + vmInfoDAO.putVmStoppedTime(writerId.getWriterID(), vmId, stopTime); MonitoredVm vm = vmData.getSecond(); vm.detach();