| 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,string,re |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | connectionStartID=1 |
|---|
| 29 | MoverQueueRegEx=re.compile("Mover Queue \((\S+)\) (.*)") |
|---|
| 30 | MoverLSRegEx=re.compile("(\d+) (\S+) (\S+) \{(\S+)\} (\S+) h=\{(\S+)\} bytes=(\d+) time/sec=(\d+) LM=(\d+)") |
|---|
| 31 | DEBUG=False |
|---|
| 32 | |
|---|
| 33 | class ourDomainEventListener( DomainEventListener) : |
|---|
| 34 | |
|---|
| 35 | def __init__(self,MyPools) : |
|---|
| 36 | self.Pools=MyPools |
|---|
| 37 | return |
|---|
| 38 | |
|---|
| 39 | def connectionOpened( self , connection ) : |
|---|
| 40 | # send first command here |
|---|
| 41 | connection.sendObject( "PoolManager" , "psu ls pool" , MyMessageListener , connectionStartID ) ; |
|---|
| 42 | |
|---|
| 43 | def connectionClosed( self , connection ) : |
|---|
| 44 | print "Connection closed" |
|---|
| 45 | |
|---|
| 46 | def connectionOutOfBand( self , connection , subject ) : |
|---|
| 47 | print "Connection out of band" |
|---|
| 48 | |
|---|
| 49 | class ourDomainConnectionListener( DomainConnectionListener ) : |
|---|
| 50 | |
|---|
| 51 | # |
|---|
| 52 | # this class only has one object in the application which |
|---|
| 53 | # is used whenever data arrives from the channel. |
|---|
| 54 | # |
|---|
| 55 | |
|---|
| 56 | def __init__( self, MyPools ) : |
|---|
| 57 | self.Pools=MyPools |
|---|
| 58 | self.currentID=connectionStartID |
|---|
| 59 | self.currentMoverID=0 |
|---|
| 60 | self.currentPoolID=0 |
|---|
| 61 | return |
|---|
| 62 | |
|---|
| 63 | def getMovers(self,obj) : |
|---|
| 64 | self.Pools.MoverInfo.append({}) |
|---|
| 65 | for line in obj.split("\n") : |
|---|
| 66 | if not "Mover Queue (" in line : continue |
|---|
| 67 | matchObj=MoverQueueRegEx.match(line) |
|---|
| 68 | if matchObj : |
|---|
| 69 | queue,conns=matchObj.groups() |
|---|
| 70 | else : |
|---|
| 71 | queue,conns=("N/A","N/A") |
|---|
| 72 | self.Pools.MoverInfo[self.currentPoolID][queue]=conns |
|---|
| 73 | self.currentPoolID +=1 |
|---|
| 74 | if self.currentPoolID < len(self.Pools.PoolList) : |
|---|
| 75 | self.currentID += 1 |
|---|
| 76 | connection.sendObject(self.Pools.PoolList[self.currentPoolID], "info",MyMessageListener, self.currentID ) |
|---|
| 77 | return |
|---|
| 78 | |
|---|
| 79 | def getDetailedMoverInfo(self,obj) : |
|---|
| 80 | self.Pools.MoverDetail.append([]) |
|---|
| 81 | for line in obj.split("\n") : |
|---|
| 82 | line=line.strip() |
|---|
| 83 | if len(line) == 0 : continue |
|---|
| 84 | tmpDict={} |
|---|
| 85 | matchObj=MoverLSRegEx.match(line) |
|---|
| 86 | if DEBUG : |
|---|
| 87 | print line,matchObj |
|---|
| 88 | if matchObj : |
|---|
| 89 | f1,State,Type,Cell,pnfsID,javastuff,bytes,speed,LM =matchObj.groups() |
|---|
| 90 | else : |
|---|
| 91 | f1,State,Type,Cell,pnfsID,javastuff,bytes,speed,LM = ("N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A") |
|---|
| 92 | tmpDict["State"]=State |
|---|
| 93 | tmpDict["Type"]=Type |
|---|
| 94 | tmpDict["Cell"]=Cell |
|---|
| 95 | tmpDict["pnfsID"]=pnfsID |
|---|
| 96 | tmpDict["Bytes"]=bytes |
|---|
| 97 | tmpDict["Speed"]=speed |
|---|
| 98 | self.Pools.MoverDetail[-1:][0].append(tmpDict) |
|---|
| 99 | self.Pools.TotalMovers += 1 |
|---|
| 100 | self.currentPoolID +=1 |
|---|
| 101 | if self.currentPoolID < len(self.Pools.PoolList) : |
|---|
| 102 | self.currentID += 1 |
|---|
| 103 | connection.sendObject(self.Pools.PoolList[self.currentPoolID], "mover ls",MyMessageListener, self.currentID ) |
|---|
| 104 | return |
|---|
| 105 | |
|---|
| 106 | def domainAnswerArrived( self , obj , id ) : |
|---|
| 107 | if DEBUG : |
|---|
| 108 | print "id=%d,border1=%d" % (id,connectionStartID + len(self.Pools.PoolList)) |
|---|
| 109 | print "currentPoolID =%d" % self.currentPoolID |
|---|
| 110 | if id == connectionStartID : |
|---|
| 111 | for p in obj.split("\n") : |
|---|
| 112 | p=p.strip() |
|---|
| 113 | if len(p) == 0 :continue |
|---|
| 114 | self.Pools.PoolList.append(p) |
|---|
| 115 | if len(self.Pools.PoolList) > 0 : |
|---|
| 116 | self.currentID += 1 |
|---|
| 117 | connection.sendObject(self.Pools.PoolList[self.currentPoolID], "info",MyMessageListener, self.currentID ) |
|---|
| 118 | elif id == connectionStartID +1 : |
|---|
| 119 | self.getMovers(obj) |
|---|
| 120 | elif id > connectionStartID +1 and id < connectionStartID + len(self.Pools.PoolList) : |
|---|
| 121 | self.getMovers(obj) |
|---|
| 122 | elif id == connectionStartID + len(self.Pools.PoolList) : |
|---|
| 123 | self.getMovers(obj) |
|---|
| 124 | self.currentID += 1 |
|---|
| 125 | self.currentPoolID=0 |
|---|
| 126 | connection.sendObject(self.Pools.PoolList[self.currentPoolID], "mover ls",MyMessageListener, self.currentID ) |
|---|
| 127 | elif id > connectionStartID + len(self.Pools.PoolList) and id < connectionStartID + 2 * len(self.Pools.PoolList) : |
|---|
| 128 | self.getDetailedMoverInfo(obj) |
|---|
| 129 | else : |
|---|
| 130 | self.getDetailedMoverInfo(obj) |
|---|
| 131 | self.Pools.html_dump() |
|---|
| 132 | System.exit(0) |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | class Pools : |
|---|
| 137 | |
|---|
| 138 | def __init__(self) : |
|---|
| 139 | self.PoolList=[] |
|---|
| 140 | self.MoverInfo=[] |
|---|
| 141 | self.MoverDetail=[] |
|---|
| 142 | self.TotalMovers=0 |
|---|
| 143 | return |
|---|
| 144 | |
|---|
| 145 | def dump(self) : |
|---|
| 146 | self.PoolList.sort() |
|---|
| 147 | print "PoolList : %s" % string.join(self.PoolList,",") |
|---|
| 148 | print "Info :" |
|---|
| 149 | for i in range(len(self.PoolList)) : |
|---|
| 150 | print "Mover queues Pool %s :" % self.PoolList[i] |
|---|
| 151 | for q in self.MoverInfo[i] : |
|---|
| 152 | print "* %s : %s " % (q,self.MoverInfo[i][q]) |
|---|
| 153 | for i in range(len(self.PoolList)) : |
|---|
| 154 | print "Detailed Mover info Pool %s :" % self.PoolList[i] |
|---|
| 155 | for j in range(len(self.MoverDetail[i])) : |
|---|
| 156 | for q in self.MoverDetail[i][j] : |
|---|
| 157 | print "%s : %s " % (q,self.MoverDetail[i][j][q]) |
|---|
| 158 | print "-------------" |
|---|
| 159 | return |
|---|
| 160 | |
|---|
| 161 | def html_dump(self) : |
|---|
| 162 | print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|---|
| 163 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
|---|
| 164 | |
|---|
| 165 | <head> |
|---|
| 166 | <title>HIP/CSC Storage Element</title> |
|---|
| 167 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
|---|
| 168 | <meta http-equiv="Refresh" content="60"> |
|---|
| 169 | <link rel="stylesheet" type="text/css" href="/duchess.css"> |
|---|
| 170 | <!-- sorttable from http://www.kryogenix.org/code/browser/sorttable/ --> |
|---|
| 171 | <script src="/sorttable.js"></script> |
|---|
| 172 | </head> |
|---|
| 173 | <body> |
|---|
| 174 | """ |
|---|
| 175 | print "<h1>All Active Connections</h1>" |
|---|
| 176 | print "Updated at: %s<br/>" % time.asctime(time.localtime()) |
|---|
| 177 | print "Total number of movers : %s<br/>" % self.TotalMovers |
|---|
| 178 | print "<i>For sorting by column click on the table headers</i><br/>" |
|---|
| 179 | print '<table border="1" class="sortable">' |
|---|
| 180 | print "<thead><tr>" |
|---|
| 181 | print "<th>Pool</th>" |
|---|
| 182 | print "<th>Cell</th>" |
|---|
| 183 | print "<th>Type</th>" |
|---|
| 184 | print "<th>State</th>" |
|---|
| 185 | print "<th>Speed</th>" |
|---|
| 186 | print "<th>pnfsID</th>" |
|---|
| 187 | print "<th>Bytes</th>" |
|---|
| 188 | print "</tr></thead>" |
|---|
| 189 | print "<tbody>" |
|---|
| 190 | for i in range(len(self.PoolList)) : |
|---|
| 191 | for j in range(len(self.MoverDetail[i])) : |
|---|
| 192 | print "<tr>" |
|---|
| 193 | print "<td> %s</td>" % self.PoolList[i] |
|---|
| 194 | print "<td>%s</td>" % (self.MoverDetail[i][j]["Cell"]) |
|---|
| 195 | print "<td>%s</td>" % (self.MoverDetail[i][j]["Type"]) |
|---|
| 196 | print "<td>%s</td>" % (self.MoverDetail[i][j]["State"]) |
|---|
| 197 | print "<td>%s</td>" % (self.MoverDetail[i][j]["Speed"]) |
|---|
| 198 | print "<td>%s</td>" % (self.MoverDetail[i][j]["pnfsID"]) |
|---|
| 199 | print "<td>%s</td>" % (self.MoverDetail[i][j]["Bytes"]) |
|---|
| 200 | print "</tr>" |
|---|
| 201 | print "</tbody>" |
|---|
| 202 | print "</table>" |
|---|
| 203 | |
|---|
| 204 | print "</body></html>" |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | #---------------------------------------------------------------------- |
|---|
| 208 | # |
|---|
| 209 | # Main Routine |
|---|
| 210 | # |
|---|
| 211 | #---------------------------------------------------------------------- |
|---|
| 212 | # |
|---|
| 213 | if len(sys.argv) < 5 : |
|---|
| 214 | print "Usage : ... <hostname> <portNumber> <userName> <passwd>" |
|---|
| 215 | System.exit(4) |
|---|
| 216 | # |
|---|
| 217 | # Define the ListenerObject for all incoming message |
|---|
| 218 | # |
|---|
| 219 | |
|---|
| 220 | MyPools=Pools() |
|---|
| 221 | MyMessageListener = ourDomainConnectionListener(MyPools) |
|---|
| 222 | MyDomainEventListener=ourDomainEventListener(MyPools) |
|---|
| 223 | # |
|---|
| 224 | # Define Host and portnumber |
|---|
| 225 | # |
|---|
| 226 | connection=Ssh1DomainConnection(sys.argv[1],int(sys.argv[2])) |
|---|
| 227 | connection.setLoginName(sys.argv[3]) |
|---|
| 228 | # |
|---|
| 229 | # Establish the secret : either password or identity file |
|---|
| 230 | # |
|---|
| 231 | |
|---|
| 232 | secret=sys.argv[4] |
|---|
| 233 | if secret[0] == "/" : |
|---|
| 234 | connection.setPassword("") |
|---|
| 235 | try : |
|---|
| 236 | connection.setIdentityFile( File(secret) ) |
|---|
| 237 | except FileNotFoundException, e : |
|---|
| 238 | print "Authentication Failed ...",e.getMessage() |
|---|
| 239 | System.exit(1) |
|---|
| 240 | else : |
|---|
| 241 | connection.setPassword(secret) |
|---|
| 242 | |
|---|
| 243 | connection.addDomainEventListener( MyDomainEventListener ) |
|---|
| 244 | # |
|---|
| 245 | # and now go |
|---|
| 246 | # |
|---|
| 247 | try : |
|---|
| 248 | connection.go() |
|---|
| 249 | except SshAuthenticationException, e : |
|---|
| 250 | print "Authentication Failed ...",e.getMessage() |
|---|
| 251 | System.exit(1) |
|---|
| 252 | |
|---|