// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.network.resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.DirectNetworkUsageAnswer;
import com.cloud.agent.api.DirectNetworkUsageCommand;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RecurringNetworkUsageAnswer;
import com.cloud.agent.api.RecurringNetworkUsageCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupTrafficMonitorCommand;
import com.cloud.host.Host;
import com.cloud.resource.ServerResource;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.exception.ExecutionException;
public class TrafficSentinelResource implements ServerResource {
private String _name;
private String _zoneId;
private String _ip;
private String _guid;
private String _url;
private static Integer _numRetries;
private static Integer _timeoutInSeconds;
private static final Logger s_logger = Logger.getLogger(TrafficSentinelResource.class);
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
try {
_name = name;
_zoneId = (String) params.get("zone");
if (_zoneId == null) {
throw new ConfigurationException("Unable to find zone");
}
_ip = (String) params.get("ipaddress");
if (_ip == null) {
throw new ConfigurationException("Unable to find IP");
}
_guid = (String)params.get("guid");
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid");
}
_url = (String)params.get("url");
if (_url == null) {
throw new ConfigurationException("Unable to find url");
}
_numRetries = NumbersUtil.parseInt((String) params.get("numRetries"), 1);
_timeoutInSeconds = NumbersUtil.parseInt((String) params.get("timeoutInSeconds"), 300);
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
}
}
@Override
public StartupCommand[] initialize() {
StartupTrafficMonitorCommand cmd = new StartupTrafficMonitorCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod("");
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public Host.Type getType() {
return Host.Type.TrafficMonitor;
}
@Override
public String getName() {
return _name;
}
@Override
public PingCommand getCurrentStatus(final long id) {
return new PingCommand(Host.Type.TrafficMonitor, id);
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public void disconnected() {
return;
}
@Override
public IAgentControl getAgentControl() {
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
return;
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand) cmd);
} else if (cmd instanceof DirectNetworkUsageCommand) {
return execute((DirectNetworkUsageCommand) cmd);
} else if (cmd instanceof RecurringNetworkUsageCommand) {
return execute((RecurringNetworkUsageCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
private Answer execute(ReadyCommand cmd) {
return new ReadyAnswer(cmd);
}
private synchronized RecurringNetworkUsageAnswer execute(RecurringNetworkUsageCommand cmd) {
return new RecurringNetworkUsageAnswer(cmd);
}
private synchronized DirectNetworkUsageAnswer execute(DirectNetworkUsageCommand cmd) {
try {
return getPublicIpBytesSentAndReceived(cmd);
} catch (ExecutionException e) {
return new DirectNetworkUsageAnswer(cmd, e);
}
}
private Answer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd);
}
private DirectNetworkUsageAnswer getPublicIpBytesSentAndReceived(DirectNetworkUsageCommand cmd) throws ExecutionException {
DirectNetworkUsageAnswer answer = new DirectNetworkUsageAnswer(cmd);
try {
//Direct Network Usage
URL trafficSentinel;
try {
//Query traffic Sentinel
trafficSentinel = new URL(_url+"/inmsf/Query?script="+URLEncoder.encode(getScript(cmd.getPublicIps(), cmd.getStart(), cmd.getEnd()),"UTF-8")
+"&authenticate=basic&resultFormat=txt");
BufferedReader in = new BufferedReader(
new InputStreamReader(trafficSentinel.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null){
//Parse the script output
StringTokenizer st = new StringTokenizer(inputLine, ",");
if(st.countTokens() == 3){
String publicIp = st.nextToken();
Long bytesSent = new Long(st.nextToken());
Long bytesRcvd = new Long(st.nextToken());
if(bytesSent == null || bytesRcvd == null){
s_logger.debug("Incorrect bytes for IP: "+publicIp);
}
long[] bytesSentAndReceived = new long[2];
bytesSentAndReceived[0] = bytesSent;
bytesSentAndReceived[1] = bytesRcvd;
answer.put(publicIp, bytesSentAndReceived);
}
}
in.close();
} catch (MalformedURLException e1) {
s_logger.info("Invalid Traffic Sentinel URL",e1);
throw new ExecutionException(e1.getMessage());
} catch (IOException e) {
s_logger.debug("Error in direct network usage accounting",e);
throw new ExecutionException(e.getMessage());
}
} catch (Exception e) {
s_logger.debug(e);
throw new ExecutionException(e.getMessage());
}
return answer;
}
private String getScript(List<String> Ips, Date start, Date end){
String IpAddresses = "";
for(int i=0; i<Ips.size(); i++ ){
IpAddresses += Ips.get(i);
if(i != (Ips.size() - 1)){
// Append comma for all Ips except the last Ip
IpAddresses += ",";
}
}
String startDate = getDateString(start);
String endtDate = getDateString(end);
StringBuffer sb = new StringBuffer();
sb.append("var q = Query.topN(\"historytrmx\",");
sb.append(" \"ipsource,bytes\",");
sb.append(" \"ipsource = "+IpAddresses+" & destinationzone = EXTERNAL\",");
sb.append(" \""+startDate+", "+endtDate+"\",");
sb.append(" \"bytes\",");
sb.append(" 100000);");
sb.append("var totalsSent = {};");
sb.append("var t = q.run(");
sb.append(" function(row,table) {");
sb.append(" if(row[0]) { ");
sb.append(" totalsSent[row[0]] = row[1];");
sb.append(" }");
sb.append(" });");
sb.append("var q = Query.topN(\"historytrmx\",");
sb.append(" \"ipdestination,bytes\",");
sb.append(" \"ipdestination = "+IpAddresses+" & sourcezone = EXTERNAL\",");
sb.append(" \""+startDate+", "+endtDate+"\",");
sb.append(" \"bytes\",");
sb.append(" 100000);");
sb.append("var totalsRcvd = {};");
sb.append("var t = q.run(");
sb.append(" function(row,table) {");
sb.append(" if(row[0]) {");
sb.append(" totalsRcvd[row[0]] = row[1];");
sb.append(" }");
sb.append(" });");
sb.append("for (var addr in totalsSent) {");
sb.append(" var TS = 0;");
sb.append(" var TR = 0;");
sb.append(" if(totalsSent[addr]) TS = totalsSent[addr];");
sb.append(" if(totalsRcvd[addr]) TR = totalsRcvd[addr];");
sb.append(" println(addr + \",\" + TS + \",\" + TR);");
sb.append("}");
return sb.toString();
}
private String getDateString(Date date){
DateFormat dfDate = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
return dfDate.format(date);
}
}