better way to log the agent request and response. Introduced the idea of via agents in the request header

This commit is contained in:
Alex Huang 2011-05-17 15:40:57 -07:00
parent e552f118af
commit 0ba6091ca7
23 changed files with 417 additions and 387 deletions

View File

@ -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<String, String> contextMap = new HashMap<String, String>();
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<String, VmStatsEntry> vmStatsMap;
public GetVmStatsAnswer(GetVmStatsCommand cmd, HashMap<String, VmStatsEntry> vmStatsMap) {
super(cmd);
this.vmStatsMap = vmStatsMap;
}
public HashMap<String, VmStatsEntry> getVmStatsMap() {
return vmStatsMap;
}
protected GetVmStatsAnswer() {
//no-args constructor for json serialization-deserialization
}
@Override
public boolean logTrace() {
return true;
HashMap<String, VmStatsEntry> vmStatsMap;
public GetVmStatsAnswer(GetVmStatsCommand cmd, HashMap<String, VmStatsEntry> vmStatsMap) {
super(cmd);
this.vmStatsMap = vmStatsMap;
}
public HashMap<String, VmStatsEntry> getVmStatsMap() {
return vmStatsMap;
}
protected GetVmStatsAnswer() {
//no-args constructor for json serialization-deserialization
}
}

View File

@ -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<String> vmNames;
String hostGuid;
String hostName;
protected GetVmStatsCommand() {
}
public GetVmStatsCommand(List<String> vmNames, String hostGuid, String hostName) {
this.vmNames = vmNames;
this.hostGuid = hostGuid;
this.hostName = hostName;
}
public List<String> 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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/utils"/>
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
<classpathentry combineaccessrules="false" kind="src" path="/tools"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -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<T> implements JsonDeserializer<T[]>, JsonSerializer<T[]> {
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<T> implements JsonDeserializer<T[]>, JsonSerialize
@Override
@SuppressWarnings("unchecked")
public T[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
JsonArray array = json.getAsJsonArray();
Iterator<JsonElement> it = array.iterator();
ArrayList<T> cmds = new ArrayList<T>();
Gson gson = s_gBuilder.create();
while (it.hasNext()) {
JsonObject element = (JsonObject)it.next();
Map.Entry<String, JsonElement> entry = element.entrySet().iterator().next();
String name = s_pkg + entry.getKey();
Class<?> clazz;
try {
@ -81,7 +80,7 @@ public class ArrayTypeAdaptor<T> implements JsonDeserializer<T[]>, 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();

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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;
}
}

View File

@ -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<Command>());
builder.registerTypeAdapter(Answer[].class, new ArrayTypeAdaptor<Answer>());
public static Gson setDefaultGsonConfig(GsonBuilder builder) {
ArrayTypeAdaptor<Command> cmdAdaptor = new ArrayTypeAdaptor<Command>();
builder.registerTypeAdapter(Command[].class, cmdAdaptor);
ArrayTypeAdaptor<Answer> ansAdaptor = new ArrayTypeAdaptor<Answer>();
builder.registerTypeAdapter(Answer[].class, ansAdaptor);
builder.registerTypeAdapter(new TypeToken<List<PortConfig>>() {
}.getType(), new PortConfigListTypeAdaptor());
builder.registerTypeAdapter(new TypeToken<Pair<Long, Long>>() {
}.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<Command> cmdListTonotLog = new ArrayList<Command>();
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<Command> 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<Long, Long> 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<PortConfig>();
}
Gson jsonp = s_gBuilder.create();
List<PortConfig> pcs = new ArrayList<PortConfig>();
JsonArray array = json.getAsJsonArray();
Iterator<JsonElement> 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;
}

View File

@ -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: ";

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<List<VolumeVO>>, JsonSerializer<List<VolumeVO>> {
static final GsonBuilder s_gBuilder;
static {
s_gBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
}
Type listType = new TypeToken<List<VolumeVO>>() {}.getType();
public VolListTypeAdaptor() {
}
public JsonElement serialize(List<VolumeVO> src, Type typeOfSrc, JsonSerializationContext context) {
Gson json = s_gBuilder.create();
String result = json.toJson(src, listType);
return new JsonPrimitive(result);
}
public List<VolumeVO> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String jsonString = json.getAsJsonPrimitive().getAsString();
Gson jsonp = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
List<VolumeVO> vols = jsonp.fromJson(jsonString, listType);
return vols;
}
}

View File

@ -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<Command>());
s_gBuilder.registerTypeAdapter(Answer[].class, new ArrayTypeAdaptor<Answer>());
Type listType = new TypeToken<List<VolumeVO>>() {}.getType();
s_gBuilder.registerTypeAdapter(listType, new VolListTypeAdaptor());
}
public static GsonBuilder getBuilder() {

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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());
}
}
}

View File

@ -246,8 +246,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_name = name;
Request.initBuilder();
final ComponentLocator locator = ComponentLocator.getCurrentLocator();
ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
if (configDao == null) {