From 0ba6091ca702da65751689830d407b58b4e0d025 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Tue, 17 May 2011 15:40:57 -0700 Subject: [PATCH] better way to log the agent request and response. Introduced the idea of via agents in the request header --- api/src/com/cloud/agent/api/Command.java | 10 +- .../cloud/agent/api/GetFileStatsAnswer.java | 11 +- .../cloud/agent/api/GetFileStatsCommand.java | 13 +- .../cloud/agent/api/GetHostStatsAnswer.java | 65 ++++---- .../cloud/agent/api/GetHostStatsCommand.java | 27 ++-- .../agent/api/GetStorageStatsAnswer.java | 21 ++- .../agent/api/GetStorageStatsCommand.java | 17 +- .../com/cloud/agent/api/GetVmStatsAnswer.java | 36 ++--- .../cloud/agent/api/GetVmStatsCommand.java | 24 ++- api/src/com/cloud/agent/api/LogLevel.java | 16 +- .../cloud/agent/api/ModifySshKeysCommand.java | 49 +++--- .../cloud/agent/api/NetworkUsageAnswer.java | 22 ++- .../cloud/agent/api/NetworkUsageCommand.java | 25 ++- .../agent/api/UpdateHostPasswordCommand.java | 11 +- core/.classpath | 2 + .../agent/transport/ArrayTypeAdaptor.java | 25 ++- .../transport/LoggingExclusionStrategy.java | 56 +++++++ .../com/cloud/agent/transport/Request.java | 152 ++++++++---------- .../com/cloud/agent/transport/Response.java | 40 +++-- .../agent/transport/VolListTypeAdaptor.java | 60 ------- core/src/com/cloud/serializer/GsonHelper.java | 10 -- .../agent/api/transport/RequestTest.java | 110 +++++++++++++ .../cloud/agent/manager/AgentManagerImpl.java | 2 - 23 files changed, 417 insertions(+), 387 deletions(-) create mode 100644 core/src/com/cloud/agent/transport/LoggingExclusionStrategy.java delete mode 100644 core/src/com/cloud/agent/transport/VolListTypeAdaptor.java create mode 100644 core/test/com/cloud/agent/api/transport/RequestTest.java diff --git a/api/src/com/cloud/agent/api/Command.java b/api/src/com/cloud/agent/api/Command.java index 544e6c2dee1..b576108153f 100755 --- a/api/src/com/cloud/agent/api/Command.java +++ b/api/src/com/cloud/agent/api/Command.java @@ -28,10 +28,10 @@ import com.cloud.agent.api.LogLevel.Log4jLevel; * all of the methods that needs to be implemented by the children classes. * */ -@LogLevel(level = Log4jLevel.Debug) public abstract class Command { // allow command to carry over hypervisor or other environment related context info + @LogLevel(Log4jLevel.Trace) protected Map contextMap = new HashMap(); protected Command() { @@ -56,12 +56,4 @@ public abstract class Command { public String getContextParam(String name) { return contextMap.get(name); } - - public boolean logTrace() { - return false; - } - - public boolean doNotLogCommandParams() { - return false; - } } diff --git a/api/src/com/cloud/agent/api/GetFileStatsAnswer.java b/api/src/com/cloud/agent/api/GetFileStatsAnswer.java index fdb168cec40..da0611ea972 100755 --- a/api/src/com/cloud/agent/api/GetFileStatsAnswer.java +++ b/api/src/com/cloud/agent/api/GetFileStatsAnswer.java @@ -17,25 +17,22 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.storage.VolumeStats; +@LogLevel(Log4jLevel.Trace) public class GetFileStatsAnswer extends Answer implements VolumeStats { long size; protected GetFileStatsAnswer() { } - + public GetFileStatsAnswer(GetFileStatsCommand cmd, long value) { super(cmd); size = value; } - + @Override public long getBytesUsed() { return size; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/GetFileStatsCommand.java b/api/src/com/cloud/agent/api/GetFileStatsCommand.java index 3584abb196f..e15af024062 100755 --- a/api/src/com/cloud/agent/api/GetFileStatsCommand.java +++ b/api/src/com/cloud/agent/api/GetFileStatsCommand.java @@ -17,14 +17,16 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.storage.Volume; +@LogLevel(Log4jLevel.Trace) public class GetFileStatsCommand extends Command { protected GetFileStatsCommand() { } - + String paths; - + public GetFileStatsCommand(Volume volume) { paths = volume.getPath(); } @@ -32,14 +34,9 @@ public class GetFileStatsCommand extends Command { public String getPaths() { return paths; } - + @Override public boolean executeInSequence() { return false; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/GetHostStatsAnswer.java b/api/src/com/cloud/agent/api/GetHostStatsAnswer.java index b52a4e04422..5fb3b5dba8c 100755 --- a/api/src/com/cloud/agent/api/GetHostStatsAnswer.java +++ b/api/src/com/cloud/agent/api/GetHostStatsAnswer.java @@ -17,30 +17,32 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.host.HostStats; /** * @author ajoshi * */ +@LogLevel(Log4jLevel.Trace) public class GetHostStatsAnswer extends Answer implements HostStats { - - HostStatsEntry hostStats; + + HostStatsEntry hostStats; protected GetHostStatsAnswer() { - hostStats = new HostStatsEntry(); + hostStats = new HostStatsEntry(); } - - public GetHostStatsAnswer(GetHostStatsCommand cmd, HostStatsEntry hostStatistics) { - super(cmd); - this.hostStats = hostStatistics; - } - - public GetHostStatsAnswer(GetHostStatsCommand cmd, double cpuUtilization, double freeMemoryKBs, double totalMemoryKBs, double networkReadKBs, - double networkWriteKBs, String entityType) { + + public GetHostStatsAnswer(GetHostStatsCommand cmd, HostStatsEntry hostStatistics) { + super(cmd); + this.hostStats = hostStatistics; + } + + public GetHostStatsAnswer(GetHostStatsCommand cmd, double cpuUtilization, double freeMemoryKBs, double totalMemoryKBs, double networkReadKBs, + double networkWriteKBs, String entityType) { super(cmd); hostStats = new HostStatsEntry(); - + hostStats.setCpuUtilization(cpuUtilization); hostStats.setFreeMemoryKBs(freeMemoryKBs); hostStats.setTotalMemoryKBs(totalMemoryKBs); @@ -48,49 +50,44 @@ public class GetHostStatsAnswer extends Answer implements HostStats { hostStats.setNetworkWriteKBs(networkWriteKBs); hostStats.setEntityType(entityType); } - + @Override public double getUsedMemory() { - return hostStats.getUsedMemory(); + return hostStats.getUsedMemory(); } - + @Override public double getFreeMemoryKBs() { return hostStats.getFreeMemoryKBs(); } - + @Override public double getTotalMemoryKBs() { - return hostStats.getTotalMemoryKBs(); + return hostStats.getTotalMemoryKBs(); } - + @Override public double getCpuUtilization() { return hostStats.getCpuUtilization(); } - + @Override public double getNetworkReadKBs() { - return hostStats.getNetworkReadKBs(); + return hostStats.getNetworkReadKBs(); } - + @Override public double getNetworkWriteKBs() { - return hostStats.getNetworkWriteKBs(); + return hostStats.getNetworkWriteKBs(); } - @Override - public String getEntityType() { - return hostStats.getEntityType(); - } - - @Override - public HostStats getHostStats() { - return hostStats; - } - @Override - public boolean logTrace() { - return true; + public String getEntityType() { + return hostStats.getEntityType(); + } + + @Override + public HostStats getHostStats() { + return hostStats; } } diff --git a/api/src/com/cloud/agent/api/GetHostStatsCommand.java b/api/src/com/cloud/agent/api/GetHostStatsCommand.java index 7adc78f055b..4ae5bfef197 100755 --- a/api/src/com/cloud/agent/api/GetHostStatsCommand.java +++ b/api/src/com/cloud/agent/api/GetHostStatsCommand.java @@ -17,41 +17,38 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; -public class GetHostStatsCommand extends Command +@LogLevel(Log4jLevel.Trace) +public class GetHostStatsCommand extends Command { String hostGuid; String hostName; long hostId; - + protected GetHostStatsCommand() { } - + public GetHostStatsCommand(String hostGuid, String hostName, long hostId) { this.hostGuid = hostGuid; this.hostName = hostName; this.hostId = hostId; } - + public String getHostGuid(){ - return this.hostGuid; + return this.hostGuid; } - + public String getHostName(){ - return this.hostName; + return this.hostName; } - + public long getHostId(){ - return this.hostId; + return this.hostId; } - + @Override public boolean executeInSequence() { return false; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/GetStorageStatsAnswer.java b/api/src/com/cloud/agent/api/GetStorageStatsAnswer.java index dff8b8e74e9..4f886093f67 100755 --- a/api/src/com/cloud/agent/api/GetStorageStatsAnswer.java +++ b/api/src/com/cloud/agent/api/GetStorageStatsAnswer.java @@ -17,39 +17,36 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.storage.StorageStats; +@LogLevel(Log4jLevel.Trace) public class GetStorageStatsAnswer extends Answer implements StorageStats { protected GetStorageStatsAnswer() { } - + protected long used; - + protected long capacity; - + @Override public long getByteUsed() { return used; } - + @Override public long getCapacityBytes() { return capacity; } - - + + public GetStorageStatsAnswer(GetStorageStatsCommand cmd, long capacity, long used) { super(cmd, true, null); this.capacity = capacity; this.used = used; } - + public GetStorageStatsAnswer(GetStorageStatsCommand cmd, String details) { super(cmd, false, details); } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/GetStorageStatsCommand.java b/api/src/com/cloud/agent/api/GetStorageStatsCommand.java index 5c5184c8065..3eda95c45ac 100755 --- a/api/src/com/cloud/agent/api/GetStorageStatsCommand.java +++ b/api/src/com/cloud/agent/api/GetStorageStatsCommand.java @@ -17,13 +17,15 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.storage.Storage.StoragePoolType; +@LogLevel(Log4jLevel.Trace) public class GetStorageStatsCommand extends Command { private String id; private String localPath; private StoragePoolType pooltype; - + public GetStorageStatsCommand() { } @@ -39,12 +41,12 @@ public class GetStorageStatsCommand extends Command { public GetStorageStatsCommand(String id) { this.id = id; } - + public GetStorageStatsCommand(String id, StoragePoolType pooltype) { this.id = id; this.pooltype = pooltype; } - + public GetStorageStatsCommand(String id, StoragePoolType pooltype, String localPath) { this.id = id; this.pooltype = pooltype; @@ -54,18 +56,13 @@ public class GetStorageStatsCommand extends Command { public String getStorageId() { return this.id; } - + public String getLocalPath() { - return this.localPath; + return this.localPath; } @Override public boolean executeInSequence() { return false; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/GetVmStatsAnswer.java b/api/src/com/cloud/agent/api/GetVmStatsAnswer.java index 1a904d65728..11858e3087a 100755 --- a/api/src/com/cloud/agent/api/GetVmStatsAnswer.java +++ b/api/src/com/cloud/agent/api/GetVmStatsAnswer.java @@ -20,25 +20,23 @@ package com.cloud.agent.api; import java.util.HashMap; +import com.cloud.agent.api.LogLevel.Log4jLevel; + +@LogLevel(Log4jLevel.Trace) public class GetVmStatsAnswer extends Answer { - - HashMap vmStatsMap; - - public GetVmStatsAnswer(GetVmStatsCommand cmd, HashMap vmStatsMap) { - super(cmd); - this.vmStatsMap = vmStatsMap; - } - - public HashMap getVmStatsMap() { - return vmStatsMap; - } - - protected GetVmStatsAnswer() { - //no-args constructor for json serialization-deserialization - } - - @Override - public boolean logTrace() { - return true; + + HashMap vmStatsMap; + + public GetVmStatsAnswer(GetVmStatsCommand cmd, HashMap vmStatsMap) { + super(cmd); + this.vmStatsMap = vmStatsMap; + } + + public HashMap getVmStatsMap() { + return vmStatsMap; + } + + protected GetVmStatsAnswer() { + //no-args constructor for json serialization-deserialization } } diff --git a/api/src/com/cloud/agent/api/GetVmStatsCommand.java b/api/src/com/cloud/agent/api/GetVmStatsCommand.java index 887ef7956fc..ff7a3a0139b 100755 --- a/api/src/com/cloud/agent/api/GetVmStatsCommand.java +++ b/api/src/com/cloud/agent/api/GetVmStatsCommand.java @@ -19,39 +19,37 @@ package com.cloud.agent.api; import java.util.List; +import com.cloud.agent.api.LogLevel.Log4jLevel; + +@LogLevel(Log4jLevel.Trace) public class GetVmStatsCommand extends Command { List vmNames; String hostGuid; String hostName; - + protected GetVmStatsCommand() { } - + public GetVmStatsCommand(List vmNames, String hostGuid, String hostName) { this.vmNames = vmNames; this.hostGuid = hostGuid; this.hostName = hostName; } - + public List getVmNames() { return vmNames; } - + public String getHostGuid(){ - return this.hostGuid; + return this.hostGuid; } - + public String getHostName(){ - return this.hostName; + return this.hostName; } - + @Override public boolean executeInSequence() { return false; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/LogLevel.java b/api/src/com/cloud/agent/api/LogLevel.java index ad6b50d6ede..e5c1e3ddb2a 100644 --- a/api/src/com/cloud/agent/api/LogLevel.java +++ b/api/src/com/cloud/agent/api/LogLevel.java @@ -33,14 +33,10 @@ import org.apache.log4j.Logger; @Target({ TYPE, FIELD }) @Retention(RUNTIME) public @interface LogLevel { - public enum Log4jLevel { + public enum Log4jLevel { // Had to do this because Level is not primitive. Off(Level.OFF), Trace(Level.TRACE), - Debug(Level.DEBUG), - Info(Level.INFO), - Warn(Level.WARN), - Error(Level.ERROR), - Fatal(Level.FATAL); + Debug(Level.DEBUG); Level _level; @@ -48,14 +44,10 @@ public @interface LogLevel { _level = level; } - public void log(Logger logger, String msg) { - logger.log(_level, msg); - } - public boolean enabled(Logger logger) { - return logger.isEnabledFor(_level); + return _level != Level.OFF && logger.isEnabledFor(_level); } } - Log4jLevel level() default Log4jLevel.Debug; + Log4jLevel value() default Log4jLevel.Debug; } diff --git a/api/src/com/cloud/agent/api/ModifySshKeysCommand.java b/api/src/com/cloud/agent/api/ModifySshKeysCommand.java index 71357e16134..29190b3d614 100644 --- a/api/src/com/cloud/agent/api/ModifySshKeysCommand.java +++ b/api/src/com/cloud/agent/api/ModifySshKeysCommand.java @@ -18,34 +18,29 @@ package com.cloud.agent.api; -import com.google.gson.annotations.Expose; +import com.cloud.agent.api.LogLevel.Log4jLevel; public class ModifySshKeysCommand extends Command { - @Expose(serialize = false, deserialize = false) private String _pubKey; - @Expose(serialize = false, deserialize = false) private String _prvKey; - public ModifySshKeysCommand() { - - } - public ModifySshKeysCommand(String pubKey, String prvKey) { - _pubKey = pubKey; - _prvKey = prvKey; - } - public String getPubKey() { - return _pubKey; - } - public String getPrvKey() { - return _prvKey; - } - @Override - public boolean executeInSequence() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean doNotLogCommandParams(){ - return true; + @LogLevel(Log4jLevel.Off) + private String _pubKey; + @LogLevel(Log4jLevel.Off) + private String _prvKey; + + public ModifySshKeysCommand() { + + } + public ModifySshKeysCommand(String pubKey, String prvKey) { + _pubKey = pubKey; + _prvKey = prvKey; + } + public String getPubKey() { + return _pubKey; + } + public String getPrvKey() { + return _prvKey; + } + @Override + public boolean executeInSequence() { + return false; } - - } diff --git a/api/src/com/cloud/agent/api/NetworkUsageAnswer.java b/api/src/com/cloud/agent/api/NetworkUsageAnswer.java index c381982d9f1..6138f7a1314 100644 --- a/api/src/com/cloud/agent/api/NetworkUsageAnswer.java +++ b/api/src/com/cloud/agent/api/NetworkUsageAnswer.java @@ -17,38 +17,36 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; + +@LogLevel(Log4jLevel.Trace) public class NetworkUsageAnswer extends Answer { Long bytesSent; Long bytesReceived; - + protected NetworkUsageAnswer() { } - + public NetworkUsageAnswer(NetworkUsageCommand cmd, String details, Long bytesSent, Long bytesReceived) { super(cmd, true, details); this.bytesReceived = bytesReceived; this.bytesSent = bytesSent; } - - + + public void setBytesReceived(Long bytesReceived) { this.bytesReceived = bytesReceived; } - + public Long getBytesReceived() { return bytesReceived; } - + public void setBytesSent(Long bytesSent) { this.bytesSent = bytesSent; } - + public Long getBytesSent() { return bytesSent; } - - @Override - public boolean logTrace() { - return true; - } } diff --git a/api/src/com/cloud/agent/api/NetworkUsageCommand.java b/api/src/com/cloud/agent/api/NetworkUsageCommand.java index a645c9b255c..6f16bb26554 100644 --- a/api/src/com/cloud/agent/api/NetworkUsageCommand.java +++ b/api/src/com/cloud/agent/api/NetworkUsageCommand.java @@ -17,48 +17,45 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; +@LogLevel(Log4jLevel.Trace) public class NetworkUsageCommand extends Command { private String privateIP; private String domRName; private String option; - + protected NetworkUsageCommand() { - + } - + public NetworkUsageCommand(String privateIP, String domRName) { this.privateIP = privateIP; - this.domRName = domRName; + this.domRName = domRName; } - + public NetworkUsageCommand(String privateIP, String domRName, String option) { this.privateIP = privateIP; - this.domRName = domRName; + this.domRName = domRName; this.option = option; } public String getPrivateIP() { return privateIP; } - + public String getDomRName() { return domRName; } - + public String getOption() { return option; } - + @Override public boolean executeInSequence() { return false; } - - @Override - public boolean logTrace() { - return true; - } } \ No newline at end of file diff --git a/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java b/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java index 5c848e5a34c..cb0a07669c6 100644 --- a/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java +++ b/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java @@ -17,24 +17,27 @@ */ package com.cloud.agent.api; +import com.cloud.agent.api.LogLevel.Log4jLevel; public class UpdateHostPasswordCommand extends Command { + @LogLevel(Log4jLevel.Off) protected String _username; + @LogLevel(Log4jLevel.Off) protected String _new_password; - + protected UpdateHostPasswordCommand() { } - + public UpdateHostPasswordCommand(String username, String new_password) { this._username = username; this._new_password = new_password; } - + public String getNewPassword() { return _new_password; } - + public String getUsername() { return _username; } diff --git a/core/.classpath b/core/.classpath index a00bee99e67..ea0a6a56506 100644 --- a/core/.classpath +++ b/core/.classpath @@ -1,9 +1,11 @@ + + diff --git a/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java b/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java index 45472afa58c..b630f8778c5 100755 --- a/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java +++ b/core/src/com/cloud/agent/transport/ArrayTypeAdaptor.java @@ -27,7 +27,6 @@ import java.util.Map; import com.cloud.agent.api.Command; import com.cloud.utils.exception.CloudRuntimeException; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -39,23 +38,24 @@ import com.google.gson.JsonSerializer; public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerializer { - static final GsonBuilder s_gBuilder; - static { - s_gBuilder = Request.initBuilder(); - } - - + protected Gson _gson = null; + + private static final String s_pkg = Command.class.getPackage().getName() + "."; + public ArrayTypeAdaptor() { } + public void initGson(Gson gson) { + _gson = gson; + } + @Override public JsonElement serialize(T[] src, Type typeOfSrc, JsonSerializationContext context) { - Gson gson = s_gBuilder.create(); JsonArray array = new JsonArray(); for (T cmd : src) { JsonObject obj = new JsonObject(); - obj.add(cmd.getClass().getName().substring(s_pkg.length()), gson.toJsonTree(cmd)); + obj.add(cmd.getClass().getName().substring(s_pkg.length()), _gson.toJsonTree(cmd)); array.add(obj); } @@ -65,15 +65,14 @@ public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerialize @Override @SuppressWarnings("unchecked") public T[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { + throws JsonParseException { JsonArray array = json.getAsJsonArray(); Iterator it = array.iterator(); ArrayList cmds = new ArrayList(); - Gson gson = s_gBuilder.create(); while (it.hasNext()) { JsonObject element = (JsonObject)it.next(); Map.Entry entry = element.entrySet().iterator().next(); - + String name = s_pkg + entry.getKey(); Class clazz; try { @@ -81,7 +80,7 @@ public class ArrayTypeAdaptor implements JsonDeserializer, JsonSerialize } catch (ClassNotFoundException e) { throw new CloudRuntimeException("can't find " + name); } - T cmd = (T)gson.fromJson(entry.getValue(), clazz); + T cmd = (T)_gson.fromJson(entry.getValue(), clazz); cmds.add(cmd); } Class type = ((Class)typeOfT).getComponentType(); diff --git a/core/src/com/cloud/agent/transport/LoggingExclusionStrategy.java b/core/src/com/cloud/agent/transport/LoggingExclusionStrategy.java new file mode 100644 index 00000000000..61c14a85cba --- /dev/null +++ b/core/src/com/cloud/agent/transport/LoggingExclusionStrategy.java @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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 3 of the License, or any later version. + * This program 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 this program. If not, see . + * + */ +package com.cloud.agent.transport; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.LogLevel; +import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; + +public class LoggingExclusionStrategy implements ExclusionStrategy { + Logger _logger = null; + + @Override + public boolean shouldSkipClass(Class clazz) { + if (clazz.isArray() || !Command.class.isAssignableFrom(clazz)) { + return false; + } + Log4jLevel log4jLevel = null; + LogLevel level = clazz.getAnnotation(LogLevel.class); + if (level == null) { + log4jLevel = LogLevel.Log4jLevel.Debug; + } else { + log4jLevel = level.value(); + } + + return !log4jLevel.enabled(_logger); + } + + @Override + public boolean shouldSkipField(FieldAttributes field) { + LogLevel level = field.getAnnotation(LogLevel.class); + return level != null && !level.value().enabled(_logger); + } + + public LoggingExclusionStrategy(Logger logger) { + _logger = logger; + } +} diff --git a/core/src/com/cloud/agent/transport/Request.java b/core/src/com/cloud/agent/transport/Request.java index 2a7c8967cbc..6efeeab6327 100755 --- a/core/src/com/cloud/agent/transport/Request.java +++ b/core/src/com/cloud/agent/transport/Request.java @@ -83,29 +83,35 @@ public class Request { protected static final short FLAG_REQUEST = 0x1; protected static final short FLAG_STOP_ON_ERROR = 0x2; protected static final short FLAG_IN_SEQUENCE = 0x4; - protected static final short FLAG_REVERT_ON_ERROR = 0x8; protected static final short FLAG_FROM_SERVER = 0x20; protected static final short FLAG_CONTROL = 0x40; - protected static final GsonBuilder s_gBuilder; + protected static final Gson s_gson; + protected static final Gson s_gogger; static { - s_gBuilder = new GsonBuilder(); - setDefaultGsonConfig(s_gBuilder); + GsonBuilder gsonBuilder = new GsonBuilder(); + s_gson = setDefaultGsonConfig(gsonBuilder); + GsonBuilder loggerBuilder = new GsonBuilder(); + loggerBuilder.disableHtmlEscaping(); + loggerBuilder.setExclusionStrategies(new LoggingExclusionStrategy(s_logger)); + s_gogger = setDefaultGsonConfig(loggerBuilder); s_logger.info("Default Builder inited."); } - public static void setDefaultGsonConfig(GsonBuilder builder) { - builder.registerTypeAdapter(Command[].class, new ArrayTypeAdaptor()); - builder.registerTypeAdapter(Answer[].class, new ArrayTypeAdaptor()); + public static Gson setDefaultGsonConfig(GsonBuilder builder) { + ArrayTypeAdaptor cmdAdaptor = new ArrayTypeAdaptor(); + builder.registerTypeAdapter(Command[].class, cmdAdaptor); + ArrayTypeAdaptor ansAdaptor = new ArrayTypeAdaptor(); + builder.registerTypeAdapter(Answer[].class, ansAdaptor); builder.registerTypeAdapter(new TypeToken>() { }.getType(), new PortConfigListTypeAdaptor()); builder.registerTypeAdapter(new TypeToken>() { }.getType(), new NwGroupsCommandTypeAdaptor()); - } - - public static GsonBuilder initBuilder() { - return s_gBuilder; + Gson gson = builder.create(); + cmdAdaptor.initGson(gson); + ansAdaptor.initGson(gson); + return gson; } protected Version _ver; @@ -113,6 +119,7 @@ public class Request { protected long _seq; protected short _flags; protected long _mgmtId; + protected long _via; protected long _agentId; protected Command[] _cmds; protected String _content; @@ -120,18 +127,23 @@ public class Request { protected Request() { } - protected Request(Version ver, long seq, long agentId, long mgmtId, short flags, final Command[] cmds) { + protected Request(Version ver, long seq, long agentId, long mgmtId, long via, short flags, final Command[] cmds) { _ver = ver; _cmds = cmds; _flags = flags; _seq = seq; + _via = via; _agentId = agentId; _mgmtId = mgmtId; setInSequence(cmds); } - protected Request(Version ver, long seq, long agentId, long mgmtId, short flags, final String content) { - this(ver, seq, agentId, mgmtId, flags, (Command[]) null); + protected Request(Version ver, long seq, long agentId, long mgmtId, short flags, final Command[] cmds) { + this(ver, seq, agentId, mgmtId, agentId, flags, cmds); + } + + protected Request(Version ver, long seq, long agentId, long mgmtId, long via, short flags, final String content) { + this(ver, seq, agentId, mgmtId, via, flags, (Command[])null); _content = content; } @@ -164,6 +176,7 @@ public class Request { setStopOnError(that.stopOnError()); this._cmds = cmds; this._mgmtId = that._mgmtId; + this._via = that._via; this._agentId = that._agentId; setFromServer(!that.isFromServer()); } @@ -184,14 +197,6 @@ public class Request { _flags |= (control ? FLAG_CONTROL : 0); } - public boolean revertOnError() { - return (_flags & FLAG_CONTROL) > 0; - } - - private final void setRevertOnError(boolean revertOnError) { - _flags |= (revertOnError ? FLAG_REVERT_ON_ERROR : 0); - } - private final void setFromServer(boolean fromServer) { _flags |= (fromServer ? FLAG_FROM_SERVER : 0); } @@ -212,6 +217,10 @@ public class Request { _agentId = agentId; } + public void setVia(long agentId) { + _via = agentId; + } + public boolean executeInSequence() { return (_flags & FLAG_IN_SEQUENCE) > 0; } @@ -231,8 +240,7 @@ public class Request { public Command[] getCommands() { if (_cmds == null) { - final Gson json = s_gBuilder.create(); - _cmds = json.fromJson(_content, Command[].class); + _cmds = s_gson.fromJson(_content, Command[].class); } return _cmds; } @@ -244,17 +252,17 @@ public class Request { public String toString() { String content = _content; if (content == null) { - final Gson gson = s_gBuilder.create(); try { - content = gson.toJson(_cmds); + content = s_gson.toJson(_cmds); } catch (Throwable e) { s_logger.error("Gson serialization error on Request.toString() " + getClass().getCanonicalName(), e); } } final StringBuilder buffer = new StringBuilder(); buffer.append("{ ").append(getType()); - buffer.append(", Seq: ").append(_seq).append(", Ver: ").append(_ver.toString()).append(", MgmtId: ").append(_mgmtId).append(", AgentId: ").append(_agentId).append(", Flags: ") - .append(Integer.toBinaryString(getFlags())); + buffer.append(", Seq: ").append(_agentId).append("-").append(_seq).append(", Ver: ").append(_ver.toString()); + buffer.append(", MgmtId: ").append(_mgmtId).append(", via: ").append(_via); + buffer.append(", Flags: ").append(Integer.toBinaryString(getFlags())); buffer.append(", ").append(content).append(" }"); return buffer.toString(); } @@ -264,13 +272,14 @@ public class Request { } protected ByteBuffer serializeHeader(final int contentSize) { - final ByteBuffer buffer = ByteBuffer.allocate(32); + final ByteBuffer buffer = ByteBuffer.allocate(40); buffer.put(getVersionInByte()); buffer.put((byte) 0); buffer.putShort(getFlags()); buffer.putLong(_seq); buffer.putInt(contentSize); buffer.putLong(_mgmtId); + buffer.putLong(_via); buffer.putLong(_agentId); buffer.flip(); @@ -278,11 +287,10 @@ public class Request { } public ByteBuffer[] toBytes() { - final Gson gson = s_gBuilder.create(); final ByteBuffer[] buffers = new ByteBuffer[2]; if (_content == null) { - _content = gson.toJson(_cmds, _cmds.getClass()); + _content = s_gson.toJson(_cmds, _cmds.getClass()); } buffers[1] = ByteBuffer.wrap(_content.getBytes()); buffers[0] = serializeHeader(buffers[1].capacity()); @@ -309,58 +317,30 @@ public class Request { } public void log(long agentId, String msg) { - if (!s_logger.isDebugEnabled()) { - return; - } - StringBuilder buf = new StringBuilder("Seq "); - buf.append(agentId).append("-").append(_seq).append(": "); - boolean debug = false; + buf.append(_agentId).append("-").append(_seq).append(": "); - List cmdListTonotLog = new ArrayList(); + buf.append(msg); + buf.append("{ ").append(getType()); + buf.append(", Ver: ").append(_ver.toString()); + buf.append(", MgmtId: ").append(_mgmtId).append(", via: ").append(_via); + buf.append(", Flags: ").append(Integer.toBinaryString(getFlags())).append(", "); if (_cmds != null) { - for (Command cmd : _cmds) { - if (cmd.doNotLogCommandParams()) { - cmdListTonotLog.add(cmd); - } - } - } - - if (_cmds != null) { - for (Command cmd : _cmds) { - if (!cmd.logTrace()) { - debug = true; - break; - } + try { + s_gogger.toJson(_cmds, buf); + } catch (Throwable e) { + s_logger.error("Gson serialization error on Request.toString() " + getClass().getCanonicalName(), e); + return; } + } else if (_content != null) { + buf.append(_content.subSequence(0, 32)); } else { - debug = true; + buf.append("I've got nada here!"); + assert false : "How can both commands and content be null? What are we sending here?"; } + buf.append(" }"); - buf.append(msg).append(toString()); - - if (!cmdListTonotLog.isEmpty()) { - removeCmdContentFromLog(cmdListTonotLog, buf); - } - - if (executeInSequence() || debug) { - s_logger.debug(buf.toString()); - } else { - s_logger.trace(buf.toString()); - } - } - - private void removeCmdContentFromLog(List cmdListTonotLog, StringBuilder buf) { - for (Command cmd : cmdListTonotLog) { - int cmdNameIndex = buf.indexOf(cmd.toString()); - if (cmdNameIndex != -1) { - int colonIndex = buf.indexOf(":", cmdNameIndex); - int cmdEndIndex = buf.indexOf("]", cmdNameIndex); - if (colonIndex != -1 && cmdEndIndex != -1) { - buf.replace(colonIndex + 1, cmdEndIndex, "{}}"); - } - } - } + s_logger.debug(buf.toString()); } /** @@ -388,6 +368,7 @@ public class Request { final long seq = buff.getLong(); final int size = buff.getInt(); final long mgmtId = buff.getLong(); + final long via = buff.getLong(); final long agentId = buff.getLong(); byte[] command = null; @@ -404,9 +385,9 @@ public class Request { final String content = new String(command, offset, command.length - offset); if (isRequest) { - return new Request(version, seq, agentId, mgmtId, flags, content); + return new Request(version, seq, agentId, mgmtId, via, flags, content); } else { - return new Response(Version.get(ver), seq, agentId, mgmtId, flags, content); + return new Response(Version.get(ver), seq, agentId, mgmtId, via, flags, content); } } @@ -414,6 +395,10 @@ public class Request { return _agentId; } + public long getViaAgentId() { + return _via; + } + public static boolean requiresSequentialExecution(final byte[] bytes) { return (bytes[3] & FLAG_IN_SEQUENCE) > 0; } @@ -458,15 +443,14 @@ public class Request { @Override public JsonElement serialize(Pair src, java.lang.reflect.Type typeOfSrc, JsonSerializationContext context) { JsonArray array = new JsonArray(); - Gson json = s_gBuilder.create(); if (src.first() != null) { - array.add(json.toJsonTree(src.first())); + array.add(s_gson.toJsonTree(src.first())); } else { array.add(new JsonNull()); } if (src.second() != null) { - array.add(json.toJsonTree(src.second())); + array.add(s_gson.toJsonTree(src.second())); } else { array.add(new JsonNull()); } @@ -507,11 +491,10 @@ public class Request { s_logger.info("Returning JsonNull"); return new JsonNull(); } - Gson json = s_gBuilder.create(); s_logger.debug("Returning gson tree"); JsonArray array = new JsonArray(); for (PortConfig pc : src) { - array.add(json.toJsonTree(pc)); + array.add(s_gson.toJsonTree(pc)); } return array; @@ -522,13 +505,12 @@ public class Request { if (json.isJsonNull()) { return new ArrayList(); } - Gson jsonp = s_gBuilder.create(); List pcs = new ArrayList(); JsonArray array = json.getAsJsonArray(); Iterator it = array.iterator(); while (it.hasNext()) { JsonElement element = it.next(); - pcs.add(jsonp.fromJson(element, PortConfig.class)); + pcs.add(s_gson.fromJson(element, PortConfig.class)); } return pcs; } diff --git a/core/src/com/cloud/agent/transport/Response.java b/core/src/com/cloud/agent/transport/Response.java index da59e48350a..0d2376632a5 100755 --- a/core/src/com/cloud/agent/transport/Response.java +++ b/core/src/com/cloud/agent/transport/Response.java @@ -19,7 +19,6 @@ package com.cloud.agent.transport; import com.cloud.agent.api.Answer; import com.cloud.exception.UnsupportedVersionException; -import com.google.gson.Gson; /** * @@ -27,42 +26,41 @@ import com.google.gson.Gson; public class Response extends Request { protected Response() { } - + public Response(Request request, Answer answer) { this(request, new Answer[] { answer }); } - + public Response(Request request, Answer answer, long mgmtId, long agentId) { this(request, new Answer[] { answer }, mgmtId, agentId); } - + public Response(Request request, Answer[] answers) { super(request, answers); } - + public Response(Request request, Answer[] answers, long mgmtId, long agentId) { - super(request, answers); - _mgmtId = mgmtId; - _agentId = agentId; + super(request, answers); + _mgmtId = mgmtId; + _via = agentId; } - - protected Response(Version ver, long seq, long agentId, long mgmtId, short flags, String ans) { - super(ver, seq, agentId, mgmtId, flags, ans); + + protected Response(Version ver, long seq, long agentId, long mgmtId, long via, short flags, String ans) { + super(ver, seq, agentId, mgmtId, via, flags, ans); } - + public Answer getAnswer() { - Answer[] answers = getAnswers(); - return answers[0]; + Answer[] answers = getAnswers(); + return answers[0]; } - + public Answer[] getAnswers() { - if (_cmds == null) { - final Gson json = s_gBuilder.create(); - _cmds = json.fromJson(_content, Answer[].class); - } - return (Answer[])_cmds; + if (_cmds == null) { + _cmds = s_gson.fromJson(_content, Answer[].class); + } + return (Answer[])_cmds; } - + @Override protected String getType() { return "Ans: "; diff --git a/core/src/com/cloud/agent/transport/VolListTypeAdaptor.java b/core/src/com/cloud/agent/transport/VolListTypeAdaptor.java deleted file mode 100644 index 8615a5c3935..00000000000 --- a/core/src/com/cloud/agent/transport/VolListTypeAdaptor.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It 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 3 of the License, or any later version. - * This program 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 this program. If not, see . - * - */ -package com.cloud.agent.transport; - -import java.lang.reflect.Type; -import java.util.List; - -import com.cloud.storage.VolumeVO; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import com.google.gson.reflect.TypeToken; - -public class VolListTypeAdaptor implements JsonDeserializer>, JsonSerializer> { - static final GsonBuilder s_gBuilder; - static { - s_gBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation(); - } - - Type listType = new TypeToken>() {}.getType(); - - public VolListTypeAdaptor() { - } - - public JsonElement serialize(List src, Type typeOfSrc, JsonSerializationContext context) { - Gson json = s_gBuilder.create(); - String result = json.toJson(src, listType); - return new JsonPrimitive(result); - } - - public List deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String jsonString = json.getAsJsonPrimitive().getAsString(); - Gson jsonp = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); - List vols = jsonp.fromJson(jsonString, listType); - return vols; - } - -} \ No newline at end of file diff --git a/core/src/com/cloud/serializer/GsonHelper.java b/core/src/com/cloud/serializer/GsonHelper.java index efde449c4c4..56ae916aca0 100644 --- a/core/src/com/cloud/serializer/GsonHelper.java +++ b/core/src/com/cloud/serializer/GsonHelper.java @@ -18,18 +18,10 @@ package com.cloud.serializer; -import java.lang.reflect.Type; -import java.util.List; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; import com.cloud.agent.transport.ArrayTypeAdaptor; -import com.cloud.agent.transport.VolListTypeAdaptor; -import com.cloud.storage.VolumeVO; -import com.cloud.utils.Pair; import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; public class GsonHelper { private static final GsonBuilder s_gBuilder; @@ -38,8 +30,6 @@ public class GsonHelper { s_gBuilder.setVersion(1.3); s_gBuilder.registerTypeAdapter(Command[].class, new ArrayTypeAdaptor()); s_gBuilder.registerTypeAdapter(Answer[].class, new ArrayTypeAdaptor()); - Type listType = new TypeToken>() {}.getType(); - s_gBuilder.registerTypeAdapter(listType, new VolListTypeAdaptor()); } public static GsonBuilder getBuilder() { diff --git a/core/test/com/cloud/agent/api/transport/RequestTest.java b/core/test/com/cloud/agent/api/transport/RequestTest.java new file mode 100644 index 00000000000..66b06deb051 --- /dev/null +++ b/core/test/com/cloud/agent/api/transport/RequestTest.java @@ -0,0 +1,110 @@ +package com.cloud.agent.api.transport; + +import junit.framework.TestCase; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.SecStorageFirewallCfgCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; +import com.cloud.agent.transport.Request; +import com.cloud.agent.transport.Response; +import com.cloud.exception.UnsupportedVersionException; + +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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 3 of the License, or any later version. + * This program 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 this program. If not, see . + * + */ + +public class RequestTest extends TestCase { + private static final Logger s_logger = Logger.getLogger(RequestTest.class); + + public void testSerDeser() { + UpdateHostPasswordCommand cmd1 = new UpdateHostPasswordCommand("abc", "def"); + SecStorageFirewallCfgCommand cmd2 = new SecStorageFirewallCfgCommand(); + GetHostStatsCommand cmd3 = new GetHostStatsCommand("hostguid", "hostname", 101); + cmd2.addPortConfig("abc", "24", true, "eth0"); + cmd2.addPortConfig("127.0.0.1", "44", false, "eth1"); + Request sreq = new Request(1, 2, 3, new Command[] { cmd1, cmd2, cmd3 }, true, true); + + Logger logger = Logger.getLogger(Request.class); + Level level = logger.getLevel(); + + logger.setLevel(Level.DEBUG); + sreq.log(1, "Debug"); + + logger.setLevel(Level.TRACE); + sreq.log(1, "Trace"); + + logger.setLevel(Level.INFO); + sreq.log(1, "Info"); + + logger.setLevel(level); + + byte[] bytes = sreq.getBytes(); + Request creq = null; + try { + creq = Request.parse(bytes); + } catch (ClassNotFoundException e) { + s_logger.error("Unable to parse bytes: ", e); + } catch (UnsupportedVersionException e) { + s_logger.error("Unable to parse bytes: ", e); + } + + assert creq != null : "Couldn't get the request back"; + + compareRequest(creq, sreq); + + Answer ans = new Answer(cmd1, true, "No Problem"); + Response cresp = new Response(creq, ans); + + bytes = cresp.getBytes(); + + Response sresp = null; + try { + sresp = Response.parse(bytes); + } catch (ClassNotFoundException e) { + s_logger.error("Unable to parse bytes: ", e); + } catch (UnsupportedVersionException e) { + s_logger.error("Unable to parse bytes: ", e); + } + + assert sresp != null : "Couldn't get the response back"; + + compareRequest(cresp, sresp); + } + + protected void compareRequest(Request req1, Request req2) { + assert req1.getSequence() == req2.getSequence(); + assert req1.getAgentId() == req2.getAgentId(); + assert req1.getManagementServerId() == req2.getManagementServerId(); + assert req1.isControl() == req2.isControl(); + assert req1.isFromServer() == req2.isFromServer(); + assert req1.executeInSequence() == req2.executeInSequence(); + assert req1.stopOnError() == req2.stopOnError(); + assert req1.getVersion().equals(req2.getVersion()); + assert req1.getViaAgentId() == req2.getViaAgentId(); + Command[] cmd1 = req1.getCommands(); + Command[] cmd2 = req2.getCommands(); + for (int i = 0; i < cmd1.length; i++) { + assert cmd1[i].getClass().equals(cmd2[i].getClass()); + } + } + +} diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 7121c12fd21..412c1dcb30f 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -246,8 +246,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { public boolean configure(final String name, final Map params) throws ConfigurationException { _name = name; - Request.initBuilder(); - final ComponentLocator locator = ComponentLocator.getCurrentLocator(); ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); if (configDao == null) {