package org.dcache.srm.qos.terapaths; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import terapathsexamplejavaclient.Bandwidth; import terapathsexamplejavaclient.Bandwidths; import terapathsexamplejavaclient.ReservationData; import terapathsexamplejavaclient.ScheduleSlots; import terapathsexamplejavaclient.TpsAPI; import terapathsexamplejavaclient.TpsAPISEI; import terapathsexamplejavaclient.TpsAPI_Impl; import terapathsexamplejavaclient.Who; import javax.xml.rpc.ServiceException; import javax.xml.rpc.Stub; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.InetAddress; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Properties; import org.dcache.srm.AbstractStorageElement; import org.dcache.srm.SRM; import org.dcache.srm.qos.QOSPlugin; import org.dcache.srm.qos.QOSTicket; public class TerapathsPlugin implements QOSPlugin { private static final Logger logger = LoggerFactory.getLogger(TerapathsPlugin.class); AbstractStorageElement storage; private final Collection<QOSTicket> tickets = new ArrayList<>(); private static TpsAPISEI tpsAPISEIPort; final Properties properties = new Properties(); String propFile; Date lastRetrieval; String username; String password; String[] bandwidths; public TerapathsPlugin(){} @Override public void setSrm(SRM srm) { this.propFile = srm.getConfiguration().getQosConfigFile(); this.storage = srm.getStorage(); } @Override public QOSTicket createTicket( String credential, Long bytes, String srcURL, int srcPortMin, int srcPortMax, String srcProtocol, String dstURL, int destPortMin, int dstPortMax, String dstProtocol) { return new TerapathsTicket( credential, bytes, srcURL, srcPortMin, srcPortMax, srcProtocol, dstURL, destPortMin, dstPortMax, dstProtocol); } @Override public void addTicket(QOSTicket qosTicket) { assert(qosTicket instanceof TerapathsTicket); tickets.add(qosTicket); } @Override public boolean submit() { boolean result = true; Bandwidths[] bws; ScheduleSlots[] ss = null; long startTime = new Date().getTime(); logger.debug("Submitting qos request..."); if (lastRetrieval==null || lastRetrieval.before(lastModification())) { try { properties.load(new FileInputStream(propFile)); } catch(FileNotFoundException ex) { logger.error(ex.toString()); return false; } catch(IOException ex) { logger.error(ex.toString()); return false; } try { TpsAPI tpsAPI = new TpsAPI_Impl(); tpsAPISEIPort = tpsAPI.getTpsAPISEIPort(); ((Stub) tpsAPISEIPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, properties.getProperty("serviceUrl", "http://198.124.220.9:8080/terapathsAPI/tpsAPI?wsdl")); } catch(ServiceException ex) { logger.error(ex.toString()); return false; } catch(Exception ex) { logger.error(ex.toString()); return false; } // SSL security stuff try { System.setProperty("javax.net.ssl.keyStoreType", "JKS"); if (properties.getProperty("keyStore")!=null) { System.setProperty("javax.net.ssl.keyStore", properties .getProperty("keyStore", "/usr/java/jdk1.5.0_14/jre/lib/security/keystore")); } System.setProperty("javax.net.ssl.keyStorePassword", properties.getProperty("keyStorePassword","secret")); System.setProperty("javax.net.ssl.trustStoreType", "JKS"); if (properties.getProperty("trustStore")!=null) { System.setProperty("javax.net.ssl.trustStore", properties .getProperty("trustStore", "/usr/java/jdk1.5.0_14/jre/lib/security/cacerts2")); } System.setProperty("javax.net.ssl.trustStorePassword", properties.getProperty("trustStorePassword","secret")); } catch (Exception e) { logger.error(e.toString()); } username = properties.getProperty("username", "terapaths"); password = properties.getProperty("password", "terapaths"); String bandwidthStr = properties.getProperty("bandwidthClasses"); if (bandwidthStr != null) { bandwidths = bandwidthStr.split(","); } if (bandwidths==null || bandwidths.length==0) { bandwidths = new String[1]; bandwidths[0] = "CS1_1"; } } for (Object ticket : tickets) { TerapathsTicket tpTicket = (TerapathsTicket) ticket; // Convert names to ip address if (!(tpTicket.srcIP.toLowerCase() .equals(tpTicket.srcIP.toUpperCase()))) { try { tpTicket.srcIP = InetAddress.getByName(tpTicket.srcIP) .getHostAddress(); } catch (Exception ex) { ex.printStackTrace(); } } if (!(tpTicket.dstIP.toLowerCase() .equals(tpTicket.dstIP.toUpperCase()))) { try { tpTicket.dstIP = InetAddress.getByName(tpTicket.dstIP) .getHostAddress(); } catch (Exception ex) { ex.printStackTrace(); } } try { bws = tpsAPISEIPort .tpsAPI_getBandwidths(username, password, tpTicket.srcIP, tpTicket.dstIP); if (bws != null) { boolean successFlag = false; for (Bandwidths bw1 : bws) { if (bw1 == null) { continue; // bws[0] = local site, bws[1] = always null, bws[2] = remote site } int j = 0; for (; j < bw1.getBw().length; j++) { Bandwidth bw = bw1.getBw()[j]; // Make sure bandwidth class name is in bandwidths list from properties file int k = 0; for (; k < bandwidths.length; k++) { if (bandwidths[k].equals(bw .getClassName())) { break; } } if (k == bandwidths.length) { continue; } // Get schedule for bandwidth and time range long endTime = startTime + (long) (Double .parseDouble(properties .getProperty("extraTimePerc", "1.1")) * (((double) tpTicket.bytes) / (bw .getBandwidth() * 8)) * 1000); try { ss = tpsAPISEIPort .tpsAPI_getSchedule(username, password, "unidirectional", tpTicket.srcIP, tpTicket.dstIP, startTime, endTime, bw); } catch (Exception ex) { ex.printStackTrace(); } if (ss != null && ss.length > 0) { ReservationData rdSnd = new ReservationData(); rdSnd.setBandwidth(bw); rdSnd.setDestIp(tpTicket.dstIP); rdSnd.setDestPortMax(tpTicket.dstPortMax); rdSnd.setDestPortMin(tpTicket.dstPortMin); rdSnd.setDirection("unidirectional"); rdSnd.setDuration(Math .max((endTime - startTime) / 1000, Long .parseLong(properties .getProperty("minReservationSec", "60")))); // in seconds rdSnd.setProtocol(tpTicket.srcProtocol); rdSnd.setSrcIp(tpTicket.srcIP); rdSnd.setSrcPortMax(tpTicket.srcPortMax); rdSnd.setSrcPortMin(tpTicket.srcPortMin); rdSnd.setStartTime(startTime); rdSnd.setUserName(username); rdSnd.setWho(new Who(password)); // Convert names to ip address if (!(rdSnd.getDestIp() .toLowerCase() .equals(rdSnd .getDestIp() .toUpperCase()))) { try { rdSnd.setDestIp(InetAddress .getByName(rdSnd .getDestIp()) .getHostAddress()); } catch (Exception ex) { ex.printStackTrace(); } } if (!(rdSnd.getSrcIp() .toLowerCase() .equals(rdSnd.getSrcIp() .toUpperCase()))) { try { rdSnd.setSrcIp(InetAddress .getByName(rdSnd .getSrcIp()) .getHostAddress()); } catch (Exception ex) { ex.printStackTrace(); } } ReservationData rdRcv = tpsAPISEIPort .tpsAPI_reserve(rdSnd); if (rdRcv == null || (rdRcv .getStartTime() == rdSnd .getStartTime() && rdRcv .getDuration() == rdSnd .getDuration())) { continue; } tpTicket.id = rdRcv.getId(); tpTicket.startTime = startTime; tpTicket.endTime = endTime; tpTicket.bandwidth = rdRcv .getBandwidth() .getBandwidth(); logger.debug("Submitted qos request " + tpTicket.id); successFlag = true; break; } if (successFlag) { break; } } if (j == bw1.getBw().length) { result = false; } } } else { result = false; } } catch (RemoteException ex) { logger.error(ex.toString()); return false; } catch (Exception ex) { logger.error(ex.toString()); return false; } } return result; } @Override public void sayStatus(QOSTicket qosTicket) { assert(qosTicket instanceof TerapathsTicket); //TerapathsTicket tpTicket = (TerapathsTicket)qosTicket; //if (tpTicket.id != -1) { // Date now = new Date(); // long now = now.getTime(); // long timeLeft = tpTicket.endTime - now; // logger.debug("End time="+(tpTicket.endTime/1000)+"s now="+(now/1000)+"s expires in "+(timeLeft/1000)+"s"); // long transferTimeLeft = 0; // if (tpTicket.bytes!=-1 && tpTicket.bandwidth!=-1) // transferTimeLeft = tpTicket.bytes/(tpTicket.bandwidth*8); // TODO: change bytes to remaining bytes // if (timeLeft - transferTime < 0) // logger.debug("AM: will extend end time by "+extendTime); // else // logger.debug("AM: no need to extend end time"); // logger.debug("Ticket "+tpTicket.id+" enabled"); //} } private Date lastModification() { try { File file = new File(propFile); return new Date(file.lastModified()); } catch (Exception e) { return null; } } }