| 1 | # ---------------------------------------------------------------------- |
|---|
| 2 | # Copyright (c) 2009 CSC Ltd. (http://www.csc.fi) |
|---|
| 3 | # (All rights reversed) |
|---|
| 4 | # Based on "getPoolInfos.py" from DCACHE.ORG (R) |
|---|
| 5 | # |
|---|
| 6 | # This program is free software; you can redistribute it and/or |
|---|
| 7 | # modify it under the terms of version 2 of the GNU General Public |
|---|
| 8 | # License published by the Free Software Foundation. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU General Public License |
|---|
| 16 | # along with this program; if not, contact Novell, Inc. |
|---|
| 17 | # ---------------------------------------------------------------------- |
|---|
| 18 | # |
|---|
| 19 | from org.pcells.services.connection import * |
|---|
| 20 | from dmg.protocols.ssh import * |
|---|
| 21 | from dmg.cells.nucleus import NoRouteToCellException |
|---|
| 22 | from java.lang import System |
|---|
| 23 | from java.io import File |
|---|
| 24 | from java.io import FileNotFoundException |
|---|
| 25 | import sys,time,types |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | connectionStartID=1 |
|---|
| 29 | DEBUG=False |
|---|
| 30 | |
|---|
| 31 | class ourDomainEventListener( DomainEventListener) : |
|---|
| 32 | |
|---|
| 33 | def __init__(self,MyXrootDoor) : |
|---|
| 34 | self.XrootDoor=MyXrootDoor |
|---|
| 35 | return |
|---|
| 36 | |
|---|
| 37 | def connectionOpened( self , connection ) : |
|---|
| 38 | connection.sendObject( self.XrootDoor.CellName , "info" , MyMessageListener , connectionStartID ) ; |
|---|
| 39 | |
|---|
| 40 | def connectionClosed( self , connection ) : |
|---|
| 41 | print "Connection closed" |
|---|
| 42 | |
|---|
| 43 | def connectionOutOfBand( self , connection , subject ) : |
|---|
| 44 | print "Connection out of band" |
|---|
| 45 | |
|---|
| 46 | class ourDomainConnectionListener( DomainConnectionListener ) : |
|---|
| 47 | |
|---|
| 48 | # |
|---|
| 49 | # this class only has one object in the application which |
|---|
| 50 | # is used whenever data arrives from the channel. |
|---|
| 51 | # |
|---|
| 52 | |
|---|
| 53 | def __init__( self, MyXrootDoor ) : |
|---|
| 54 | self.XrootDoor=MyXrootDoor |
|---|
| 55 | self.currentID=connectionStartID |
|---|
| 56 | self.currentXrootKid=0 |
|---|
| 57 | return |
|---|
| 58 | |
|---|
| 59 | def getInfo(self,obj) : |
|---|
| 60 | self.currentID += 1 |
|---|
| 61 | for line in obj.split("\n") : |
|---|
| 62 | if not ":" in line :continue |
|---|
| 63 | tokens=line.split(":") |
|---|
| 64 | self.XrootDoor.Info[tokens[0].strip()]=tokens[1].strip() ; |
|---|
| 65 | connection.sendObject(self.XrootDoor.CellName, "get children",MyMessageListener, self.currentID ) |
|---|
| 66 | return |
|---|
| 67 | |
|---|
| 68 | def getChildrenNames(self,obj) : |
|---|
| 69 | self.currentID += 1 |
|---|
| 70 | for kid in obj.split("\n") : |
|---|
| 71 | if not "%s-unknow" % self.XrootDoor.CellName in kid : continue |
|---|
| 72 | self.XrootDoor.Connections.append( { |
|---|
| 73 | "CellName" : "N/A", |
|---|
| 74 | "Protocol Version": "N/A", |
|---|
| 75 | "Connected with" : "N/A", |
|---|
| 76 | "number of open files" : "N/A", |
|---|
| 77 | "number of logical streams" : "N/A" } ) |
|---|
| 78 | self.XrootDoor.Connections[-1:][0]["CellName"]=kid |
|---|
| 79 | if len(self.XrootDoor.Connections) > 0 : |
|---|
| 80 | connection.sendObject(self.XrootDoor.Connections[self.currentXrootKid]["CellName"], "info",MyMessageListener, self.currentID ) |
|---|
| 81 | return |
|---|
| 82 | |
|---|
| 83 | |
|---|
| 84 | def getChildrenInfo(self,obj) : |
|---|
| 85 | if type(obj) == types.StringType : |
|---|
| 86 | tokens=obj.split("\n") |
|---|
| 87 | self.XrootDoor.Connections[self.currentXrootKid]["Protocol Version"]=tokens[1][len("Protocol Version"):].strip() |
|---|
| 88 | self.XrootDoor.Connections[self.currentXrootKid]["Connected with"]=tokens[2][len("Connected with"):].strip() |
|---|
| 89 | self.XrootDoor.Connections[self.currentXrootKid]["number of open files"]=tokens[3][len("number of open files:"):].strip() |
|---|
| 90 | self.XrootDoor.Connections[self.currentXrootKid]["number of logical streams"]=tokens[4][len("number of logical streams:"):].strip() |
|---|
| 91 | self.currentXrootKid += 1 |
|---|
| 92 | if self.currentXrootKid < len(self.XrootDoor.Connections) : |
|---|
| 93 | self.currentID += 1 |
|---|
| 94 | connection.sendObject(self.XrootDoor.Connections[self.currentXrootKid]["CellName"], "info",MyMessageListener, self.currentID ) |
|---|
| 95 | return |
|---|
| 96 | |
|---|
| 97 | def domainAnswerArrived( self , obj , id ) : |
|---|
| 98 | if DEBUG : |
|---|
| 99 | print "id=%d,child-cutoff=%d" % (id,connectionStartID+2+len(self.XrootDoor.Connections)) |
|---|
| 100 | if id == connectionStartID : |
|---|
| 101 | self.currentID += 1 |
|---|
| 102 | connection.sendObject(self.XrootDoor.CellName, "info",MyMessageListener, self.currentID ) ; |
|---|
| 103 | elif id == connectionStartID+1 : |
|---|
| 104 | self.getInfo(obj) |
|---|
| 105 | elif id == connectionStartID+2 : |
|---|
| 106 | self.getChildrenNames(obj) |
|---|
| 107 | elif id > connectionStartID+2 and id < connectionStartID+2+len(self.XrootDoor.Connections) : |
|---|
| 108 | self.getChildrenInfo(obj) |
|---|
| 109 | elif id == connectionStartID+2+len(self.XrootDoor.Connections) : |
|---|
| 110 | self.getChildrenInfo(obj) # store the info of the last kid |
|---|
| 111 | self.currentID += 1 |
|---|
| 112 | connection.sendObject("local","logoff",MyMessageListener, self.currentID ) |
|---|
| 113 | else : |
|---|
| 114 | self.XrootDoor.html_dump() |
|---|
| 115 | System.exit(0) |
|---|
| 116 | |
|---|
| 117 | |
|---|
| 118 | |
|---|
| 119 | class XrootDoor : |
|---|
| 120 | |
|---|
| 121 | def __init__(self,CellName) : |
|---|
| 122 | self.CellName=CellName |
|---|
| 123 | self.Info={} |
|---|
| 124 | self.Connections=[] |
|---|
| 125 | return |
|---|
| 126 | |
|---|
| 127 | def dump(self) : |
|---|
| 128 | print "CellName: %s" % self.CellName |
|---|
| 129 | print "Info :" |
|---|
| 130 | for k in self.Info : |
|---|
| 131 | print "%s : %s" % (k,self.Info[k]) |
|---|
| 132 | print "Connections :" |
|---|
| 133 | for k in self.Connections: |
|---|
| 134 | print "%s" % (k) |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | def html_dump(self) : |
|---|
| 138 | print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|---|
| 139 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
|---|
| 140 | |
|---|
| 141 | <head> |
|---|
| 142 | <title>HIP/CSC Storage Element</title> |
|---|
| 143 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
|---|
| 144 | <meta http-equiv="Refresh" content="60"> |
|---|
| 145 | <link rel="stylesheet" type="text/css" href="/duchess.css"> |
|---|
| 146 | <!-- sorttable from http://www.kryogenix.org/code/browser/sorttable/ --> |
|---|
| 147 | <script src="/sorttable.js"></script> |
|---|
| 148 | </head> |
|---|
| 149 | <body> |
|---|
| 150 | """ |
|---|
| 151 | print "<h1>Statistics Xrootd-Door %s</h1>" % self.CellName |
|---|
| 152 | print "Updated at: %s<br/>" % time.asctime(time.localtime()) |
|---|
| 153 | print "<h2>Connections - Overview</h2>" |
|---|
| 154 | print '<table border="1">' |
|---|
| 155 | print "<thead><tr>" |
|---|
| 156 | print "<th>current Logins</th>" |
|---|
| 157 | print "<th>Max. current Logins</th>" |
|---|
| 158 | print "<th>Denied Logins</th>" |
|---|
| 159 | print "<th>Failed Logins</th>" |
|---|
| 160 | print "<th>Total Logins Created</th>" |
|---|
| 161 | print "</tr></thead>" |
|---|
| 162 | print "<tbody><tr>" |
|---|
| 163 | print "<td>%s</td>" % self.Info["Logins/max"].split("/")[0] |
|---|
| 164 | print "<td>%s</td>" % self.Info["Logins/max"].split("/")[1] |
|---|
| 165 | print "<td>%s</td>" % self.Info["Logins denied"] |
|---|
| 166 | print "<td>%s</td>" % self.Info["Logins failed"] |
|---|
| 167 | print "<td>%s</td>" % self.Info["Logins created"] |
|---|
| 168 | print "</tr></tbody>" |
|---|
| 169 | print "</table>" |
|---|
| 170 | |
|---|
| 171 | print "<h2>Open connections by Client</h2>" |
|---|
| 172 | print "<i>For sorting by column click on the table headers</i>" |
|---|
| 173 | print '<table border="1" class="sortable">' |
|---|
| 174 | print "<thead><tr><th>Client</th><th>number of open connections</th></tr></thead>" |
|---|
| 175 | print "<tbody>" |
|---|
| 176 | ConnsByClient={} |
|---|
| 177 | for k in self.Connections : |
|---|
| 178 | if ConnsByClient.has_key(k["Connected with"]) : |
|---|
| 179 | ConnsByClient[k["Connected with"]] += 1 |
|---|
| 180 | else : |
|---|
| 181 | ConnsByClient[k["Connected with"]] = 1 |
|---|
| 182 | tmpkeys=ConnsByClient.keys() |
|---|
| 183 | tmpkeys.sort() |
|---|
| 184 | for k in tmpkeys : |
|---|
| 185 | print "<tr>" |
|---|
| 186 | print "<td>%s</td>" % k |
|---|
| 187 | print "<td>%s</td>" % ConnsByClient[k] |
|---|
| 188 | print "</tr>" |
|---|
| 189 | print "</tbody></table>" |
|---|
| 190 | |
|---|
| 191 | print "<h2>Detailed Info of the Xrootd-Door</h2>" |
|---|
| 192 | print "<ul>" |
|---|
| 193 | tmpkeys=self.Info.keys() |
|---|
| 194 | tmpkeys.sort() |
|---|
| 195 | for k in tmpkeys : |
|---|
| 196 | print "<li><strong>%s</trong> : %s</li>" % (k,self.Info[k]) |
|---|
| 197 | print "</ul>" |
|---|
| 198 | |
|---|
| 199 | print "<h2>All open connections</h2>" |
|---|
| 200 | print "<i>For sorting by column click on the table headers</i>" |
|---|
| 201 | print '<table border="1" class="sortable">' |
|---|
| 202 | print "<thead><tr><th>CellName</th><th>Protocol Version</th><th>Connected with</th><th>number of logical streams</th><th>number of open files</th></tr></thead>" |
|---|
| 203 | print "<tbody>" |
|---|
| 204 | for k in self.Connections: |
|---|
| 205 | print "<tr>" |
|---|
| 206 | print "<td>%s</td>" % k["CellName"] |
|---|
| 207 | print "<td>%s</td>" % k["Protocol Version"] |
|---|
| 208 | print "<td>%s</td>" % k["Connected with"] |
|---|
| 209 | print "<td>%s</td>" % k["number of logical streams"] |
|---|
| 210 | print "<td>%s</td>" % k["number of open files"] |
|---|
| 211 | print "</tr>" |
|---|
| 212 | print "</tbody></table>" |
|---|
| 213 | print "</body></html>" |
|---|
| 214 | |
|---|
| 215 | |
|---|
| 216 | #---------------------------------------------------------------------- |
|---|
| 217 | # |
|---|
| 218 | # Main Routine |
|---|
| 219 | # |
|---|
| 220 | #---------------------------------------------------------------------- |
|---|
| 221 | # |
|---|
| 222 | if len(sys.argv) < 6 : |
|---|
| 223 | print "Usage : ... <hostname> <portNumber> <userName> <passwd> <Cellname>" |
|---|
| 224 | System.exit(4) |
|---|
| 225 | # |
|---|
| 226 | # Define the ListenerObject for all incoming message |
|---|
| 227 | # |
|---|
| 228 | |
|---|
| 229 | MyXrootDoor=XrootDoor(CellName=sys.argv[5]) |
|---|
| 230 | MyMessageListener = ourDomainConnectionListener(MyXrootDoor) |
|---|
| 231 | MyDomainEventListener=ourDomainEventListener(MyXrootDoor) |
|---|
| 232 | # |
|---|
| 233 | # Define Host and portnumber |
|---|
| 234 | # |
|---|
| 235 | connection=Ssh1DomainConnection(sys.argv[1],int(sys.argv[2])) |
|---|
| 236 | connection.setLoginName(sys.argv[3]) |
|---|
| 237 | # |
|---|
| 238 | # Establish the secret : either password or identity file |
|---|
| 239 | # |
|---|
| 240 | |
|---|
| 241 | secret=sys.argv[4] |
|---|
| 242 | if secret[0] == "/" : |
|---|
| 243 | connection.setPassword("") |
|---|
| 244 | try : |
|---|
| 245 | connection.setIdentityFile( File(secret) ) |
|---|
| 246 | except FileNotFoundException, e : |
|---|
| 247 | print "Authentication Failed ...",e.getMessage() |
|---|
| 248 | System.exit(1) |
|---|
| 249 | else : |
|---|
| 250 | connection.setPassword(secret) |
|---|
| 251 | |
|---|
| 252 | connection.addDomainEventListener( MyDomainEventListener ) |
|---|
| 253 | # |
|---|
| 254 | # and now go |
|---|
| 255 | # |
|---|
| 256 | try : |
|---|
| 257 | connection.go() |
|---|
| 258 | except SshAuthenticationException, e : |
|---|
| 259 | print "Authentication Failed ...",e.getMessage() |
|---|
| 260 | System.exit(1) |
|---|
| 261 | |
|---|