# ----------------------------------------------------------------------
#    Copyright (c) 2009 CSC Ltd. (http://www.csc.fi)
#    (All rights reversed)
#    Based on "getPoolInfos.py"  from DCACHE.ORG (R)
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License published by the Free Software Foundation.
#
#    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, contact Novell, Inc.
# ----------------------------------------------------------------------
#
from org.pcells.services.connection import *
from dmg.protocols.ssh import *
from dmg.cells.nucleus import NoRouteToCellException
from java.lang import System
from java.io import File
from java.io import FileNotFoundException
import sys,time,types


connectionStartID=1
DEBUG=False

class ourDomainEventListener( DomainEventListener) :

   def __init__(self,MyXrootDoor) :
       self.XrootDoor=MyXrootDoor
       return

   def connectionOpened( self , connection ) :
       connection.sendObject( self.XrootDoor.CellName , "info" , MyMessageListener , connectionStartID ) ;
       
   def connectionClosed( self , connection ) :
          print "Connection closed"

   def connectionOutOfBand( self , connection , subject ) :
          print "Connection out of band"

class ourDomainConnectionListener( DomainConnectionListener ) :

   #
   # this class only has one object in the application which
   # is used whenever data arrives from the channel.
   #

    def __init__( self, MyXrootDoor ) :
        self.XrootDoor=MyXrootDoor
        self.currentID=connectionStartID
        self.currentXrootKid=0
        return

    def getInfo(self,obj) :
        self.currentID += 1
        for line in obj.split("\n") :
            if not ":" in line :continue
            tokens=line.split(":")
            self.XrootDoor.Info[tokens[0].strip()]=tokens[1].strip() ;
        connection.sendObject(self.XrootDoor.CellName, "get children",MyMessageListener, self.currentID ) 
        return
   
    def getChildrenNames(self,obj) :
        self.currentID += 1
        for kid in obj.split("\n") :
            if not "%s-unknow" % self.XrootDoor.CellName in kid : continue
            self.XrootDoor.Connections.append( {
                                 "CellName" : "N/A",
                                 "Protocol Version": "N/A",
                                 "Connected with" : "N/A",
                                 "number of open files" : "N/A",
                                 "number of logical streams" : "N/A" } )
            self.XrootDoor.Connections[-1:][0]["CellName"]=kid
        if len(self.XrootDoor.Connections) > 0 :
            connection.sendObject(self.XrootDoor.Connections[self.currentXrootKid]["CellName"], "info",MyMessageListener, self.currentID )
        return


    def getChildrenInfo(self,obj) :
        if type(obj) == types.StringType :
            tokens=obj.split("\n")
            self.XrootDoor.Connections[self.currentXrootKid]["Protocol Version"]=tokens[1][len("Protocol Version"):].strip()
            self.XrootDoor.Connections[self.currentXrootKid]["Connected with"]=tokens[2][len("Connected with"):].strip()
            self.XrootDoor.Connections[self.currentXrootKid]["number of open files"]=tokens[3][len("number of open files:"):].strip()
            self.XrootDoor.Connections[self.currentXrootKid]["number of logical streams"]=tokens[4][len("number of logical streams:"):].strip()
        self.currentXrootKid += 1
        if self.currentXrootKid < len(self.XrootDoor.Connections) :
            self.currentID += 1
            connection.sendObject(self.XrootDoor.Connections[self.currentXrootKid]["CellName"], "info",MyMessageListener, self.currentID )
        return
  
    def domainAnswerArrived( self , obj , id ) :
       if DEBUG :
           print "id=%d,child-cutoff=%d" % (id,connectionStartID+2+len(self.XrootDoor.Connections))
       if id == connectionStartID :
          self.currentID += 1
          connection.sendObject(self.XrootDoor.CellName, "info",MyMessageListener, self.currentID ) ;
       elif id == connectionStartID+1 :
           self.getInfo(obj)
       elif id == connectionStartID+2 :
           self.getChildrenNames(obj)  
       elif id > connectionStartID+2 and id < connectionStartID+2+len(self.XrootDoor.Connections) :
           self.getChildrenInfo(obj)
       elif id == connectionStartID+2+len(self.XrootDoor.Connections) :
           self.getChildrenInfo(obj) # store the info of the last kid
           self.currentID += 1
           connection.sendObject("local","logoff",MyMessageListener, self.currentID )
       else  :
           self.XrootDoor.html_dump()
           System.exit(0)
        
    

class XrootDoor :

    def __init__(self,CellName) :
        self.CellName=CellName
        self.Info={}
        self.Connections=[]
        return

    def dump(self) :
        print "CellName: %s" % self.CellName
        print "Info :"
        for k in self.Info :
            print "%s : %s" % (k,self.Info[k])
        print "Connections :"
        for k in self.Connections:
            print "%s" % (k)


    def html_dump(self) :
        print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>HIP/CSC Storage Element</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Refresh" content="60">
<link rel="stylesheet" type="text/css" href="/duchess.css">
<!-- sorttable from http://www.kryogenix.org/code/browser/sorttable/ -->
<script src="/sorttable.js"></script>
</head>
<body>
"""
        print "<h1>Statistics Xrootd-Door %s</h1>" % self.CellName
        print "Updated at: %s<br/>" % time.asctime(time.localtime())
        print "<h2>Connections - Overview</h2>"
        print '<table border="1">'
        print "<thead><tr>"
        print "<th>current Logins</th>"
        print "<th>Max. current Logins</th>"
        print "<th>Denied Logins</th>"
        print "<th>Failed Logins</th>"
        print "<th>Total Logins Created</th>"
        print "</tr></thead>"
        print "<tbody><tr>" 
        print "<td>%s</td>" % self.Info["Logins/max"].split("/")[0]
        print "<td>%s</td>" % self.Info["Logins/max"].split("/")[1]
        print "<td>%s</td>" % self.Info["Logins denied"]
        print "<td>%s</td>" % self.Info["Logins failed"]
        print "<td>%s</td>" % self.Info["Logins created"]
        print "</tr></tbody>"
        print "</table>"

        print "<h2>Open connections by Client</h2>"
        print "<i>For sorting by column click on the table headers</i>"
        print '<table border="1" class="sortable">'
        print "<thead><tr><th>Client</th><th>number of open connections</th></tr></thead>"
        print "<tbody>"
        ConnsByClient={}
        for k in self.Connections :
            if ConnsByClient.has_key(k["Connected with"]) :
                ConnsByClient[k["Connected with"]] += 1
            else :
                ConnsByClient[k["Connected with"]] = 1
        tmpkeys=ConnsByClient.keys()   
        tmpkeys.sort()
        for k in tmpkeys : 
            print "<tr>"
            print "<td>%s</td>" % k
            print "<td>%s</td>" % ConnsByClient[k]
            print "</tr>"
        print "</tbody></table>"

        print "<h2>Detailed Info of the Xrootd-Door</h2>"
        print "<ul>"
        tmpkeys=self.Info.keys()
        tmpkeys.sort()
        for k in tmpkeys : 
            print "<li><strong>%s</trong> : %s</li>" % (k,self.Info[k])
        print "</ul>"
        
        print "<h2>All open connections</h2>"
        print "<i>For sorting by column click on the table headers</i>"
        print '<table border="1" class="sortable">'
        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>"
        print "<tbody>"
        for k in self.Connections:
            print "<tr>"
            print "<td>%s</td>" % k["CellName"]
            print "<td>%s</td>" % k["Protocol Version"]
            print "<td>%s</td>" % k["Connected with"]
            print "<td>%s</td>" % k["number of logical streams"]
            print "<td>%s</td>" % k["number of open files"]
            print "</tr>"
        print "</tbody></table>"
        print "</body></html>"


#----------------------------------------------------------------------
#
#   Main Routine
#
#----------------------------------------------------------------------
#
if  len(sys.argv) < 6 :
   print "Usage : ... <hostname> <portNumber> <userName> <passwd> <Cellname>"
   System.exit(4)
#
# Define the ListenerObject for all incoming message
#

MyXrootDoor=XrootDoor(CellName=sys.argv[5])
MyMessageListener = ourDomainConnectionListener(MyXrootDoor)
MyDomainEventListener=ourDomainEventListener(MyXrootDoor)
#
#  Define Host and portnumber
#
connection=Ssh1DomainConnection(sys.argv[1],int(sys.argv[2]))
connection.setLoginName(sys.argv[3])
#
# Establish the secret : either password or identity file
#

secret=sys.argv[4]
if secret[0] == "/" :
   connection.setPassword("")
   try :
      connection.setIdentityFile( File(secret) )
   except FileNotFoundException, e :
      print "Authentication Failed ...",e.getMessage()
      System.exit(1)
else :
   connection.setPassword(secret)

connection.addDomainEventListener( MyDomainEventListener )
#
#  and now go
#
try :
   connection.go()
except SshAuthenticationException, e :
   print "Authentication Failed ...",e.getMessage()
   System.exit(1)


