Package Ganga :: Package GPIDev :: Package Credentials :: Module AfsToken
[hide private]
[frames] | no frames]

Source Code for Module Ganga.GPIDev.Credentials.AfsToken

  1  ################################################################################
 
  2  # Ganga Project. http://cern.ch/ganga
 
  3  #
 
  4  # $Id: AfsToken.py,v 1.4 2009/03/18 18:28:15 karl Exp $
 
  5  ################################################################################
 
  6  #
 
  7  # File: AfsToken.py
 
  8  # Author: K. Harrison
 
  9  # Created: 060608
 
 10  #
 
 11  # 06/07/2006 KH:  Changed to Ganga.Utility.Shell for shell commands
 
 12  #
 
 13  # 07/08/2006 KH:  Added isValid() method
 
 14  #
 
 15  # 08/08/2006 KH:  Modified for shell being made an ICredential property
 
 16  #
 
 17  # 25/08/2006 KH:  Declare AfsToken class as hidden
 
 18  #
 
 19  # 06/09/2006 KH:  Argument minValidity added to methods create() and renew()
 
 20  #
 
 21  # 25/09/2006 KH:  Changed method isValid(), so that default validity is
 
 22  #                 value of self.minValidity
 
 23  #
 
 24  # 23/11/2006 KH:  Added "pipe" keyword to option dictionary of AfsCommand
 
 25  #                 Added method to determine if credential is available
 
 26  #                 with system/configuration used
 
 27  #                 (requests from CLT)
 
 28  #
 
 29  # 06/12/2006 KH:  Changed method timeleftInHMS(), to improve parsing
 
 30  #                 of string returned by "tokens" command
 
 31  #
 
 32  # 15/02/2007 KH:  Changed method isAvailable(), to declare credential
 
 33  #                 available only if ~/gangadir is on AFS, and the
 
 34  #                 tokens command is found
 
 35  #
 
 36  # 28/02/2007 CLT: Replaced AfsCommand.options with dictionaries
 
 37  #                 init_parameters, destroy_parameters, info_parameters,
 
 38  #                 each providing independent options
 
 39  #                 Added AfsCommand.currentOpts dictionary, to add
 
 40  #                 flexibility and assist in option construction (as opposed
 
 41  #                 to direct string manipulation)
 
 42  #                 Added AfsToken.buildOpts(), to consolidate the option
 
 43  #                 building functionality from create(), destroy() and info()
 
 44  #
 
 45  # 23/05/2007 KH:  Changed method isAvailable(), to also declare credential
 
 46  #                 available if workspace, defined via ['FileWorkspace']topdir
 
 47  #                 is on AFS, and the tokens command is found
 
 48  #
 
 49  # 24/05/2007 KH:  Changed method isAvailable(), to also declare credential
 
 50  #                 available if local repository is used, and its location,
 
 51  #                 defined via ['DefaultJobRepository']local_root
 
 52  #                 is on AFS, and the tokens command is found
 
 53  #
 
 54  # 11/06/2007 KH:  Changed logic for checking that tokens command is found
 
 55  #                 in method isAvailable()
 
 56  #
 
 57  # 25/09/2007 KH:  Additional argument (middleware) added to __init__ method
 
 58  #                 of AfsToken, for compatibility with multi-proxy handling
 
 59  #
 
 60  # 08/12/2007 KH:  Changes to take into account ICommandSet being made
 
 61  #                 a component class
 
 62  #
 
 63  # 17/12/2007 KH:  Made changes for handling of AfsTokenCommand as
 
 64  #                 component class
 
 65  #
 
 66  # 28/02/2008 KH:  Include year information when calculating time to token
 
 67  #                 expiry in timeleftInHMS() - avoid problems with leap years
 
 68  #
 
 69  # 28/02/2008 KH:  In isAvailable(), assume AFS is available if cell
 
 70  #                 is defined 
 
 71  #
 
 72  # 25/06/2008 KH: Remove separate checks on location of local workspace
 
 73  #                and local repository, which in Ganga 5 are under directory
 
 74  #                defined via ['Configuration']gangadir
 
 75  #
 
 76  # 02/07/2008 KH: Update to use requiresAfsToken() function of
 
 77  #                Ganga.Runtime.Repository_runtime to determine 
 
 78  #                whether Ganga repository is on AFS
 
 79  #
 
 80  # 18/03/2009 MWS: Added the 'log' option to isValid()
 
 81  #
 
 82  #
 
 83  # 18/03/2009 MWS: Added the 'force_check' argument to timeleft()
 
 84  #                 and timeleftInMHS()
 
 85  #
 
 86  
 
 87  """Module defining class for creating, querying and renewing AFS token""" 
 88                                                                                  
 
 89  __author__  = "K.Harrison <Harrison@hep.phy.cam.ac.uk>" 
 90  __date__    = "05 November 2009" 
 91  __version__ = "1.16" 
 92  
 
 93  import os 
 94  import time 
 95  
 
 96  from ICredential import ICommandSet 
 97  from ICredential import ICredential 
 98  from ICredential import registerCommandSet 
 99  from Ganga.GPIDev.Schema import SimpleItem 
100  from Ganga.Runtime import Repository_runtime 
101  from Ganga.Utility.Config import getConfig 
102  from Ganga.Utility.Config.Config import ConfigError 
103  from Ganga.Utility.files import fullpath 
104  from Ganga.Utility.logging import getLogger 
105  
 
106  logger = getLogger() 
107  
 
108 -class AfsCommand( ICommandSet ):
109 """ 110 Class used to define shell commands and options for working with AFS token 111 """ 112 113 _schema = ICommandSet._schema.inherit_copy() 114 _schema['init']._meta['defvalue'] = "klog" 115 _schema['info']._meta['defvalue'] = "tokens" 116 _schema['destroy']._meta['defvalue'] = "unlog" 117 _schema['init_parameters']._meta['defvalue'] = { "pipe" : "-pipe", "valid" : "-lifetime", \ 118 "username" : "-principal", "cell" : "-cell" } 119 _schema['destroy_parameters']._meta['defvalue'] = { "cell" : "-cell" } 120 121 _name = "AfsCommand" 122 _hidden = 1 123 _enable_config = 1 124
125 - def __init__( self ):
126 super( AfsCommand, self ).__init__() 127 self.currentOpts = {} 128 self.infoOpts = {} 129 self.destroyOpts = {} 130 return
131 132 registerCommandSet( AfsCommand ) 133
134 -class AfsToken ( ICredential ):
135 """ 136 Class for working with AFS token 137 """ 138 139 _schema = ICredential._schema.inherit_copy() 140 _schema.datadict[ "cell" ] = SimpleItem( defvalue = "", doc = \ 141 "AFS cell with which token is used [empty string implies local cell]" ) 142 _schema.datadict[ "username" ] = SimpleItem( defvalue = "", 143 doc = "AFS username with which token is used [defaults to login id]" ) 144 _name = "AfsToken" 145 _hidden = 1 146 _enable_config = 1 147
148 - def __init__( self, middleware = "" ):
149 super( AfsToken, self ).__init__() 150 if ( "ICommandSet" == self.command._name ): 151 self.command = AfsCommand() 152 if not self.username: 153 if os.environ.has_key( "USERNAME" ): 154 self.username = os.environ[ "USERNAME" ] 155 return
156 157 # Populate the self.command.currentOpts dictionary with 158 # AfsToken specific options.
159 - def buildOpts( self, command, clear = True):
160 if command == self.command.init: 161 if clear: 162 self.command.currentOpts.clear() 163 if self.username: 164 self.command.currentOpts[ self.command.init_parameters[ 'username' ] ] = self.username 165 if self.cell: 166 self.command.currentOpts[ self.command.init_parameters[ 'cell' ] ] = self.cell 167 if self.validityAtCreation: 168 self.command.currentOpts[ self.command.init_parameters[ 'valid' ] ] = self.validityAtCreation 169 elif command == self.command.destroy: 170 if clear: 171 self.command.destroyOpts.clear() 172 if self.cell: 173 self.command.destroyOpts[ self.command.destroy_parameters[ 'cell' ] ] = self.cell 174 elif command == self.command.info: 175 if clear: 176 self.command.infoOpts.clear()
177
178 - def create( self, validity = "", maxTry = 0, minValidity = "", check = False ):
179 self.buildOpts( self.command.init ) 180 return ICredential.create( self, validity, maxTry, minValidity, check )
181
182 - def destroy( self, allowed_exit = [ 0 ] ):
183 self.buildOpts( self.command.destroy ) 184 return ICredential.destroy( self, allowed_exit )
185
186 - def isAvailable( self ):
187 188 if self.cell: 189 available = True 190 else: 191 available = False 192 193 if not available: 194 # gangadir = fullpath( getConfig( "Configuration" )[ "gangadir" ] ) 195 # if ( 0 == gangadir.find( "/afs" ) ): 196 # available = True 197 available = Repository_runtime.requiresAfsToken() 198 199 if available: 200 infoCommand = self.command.info.split()[ 0 ] 201 available = False 202 try: 203 pathList = os.environ[ "PATH" ].split( os.pathsep ) 204 except KeyError: 205 pathList = [] 206 for searchDir in pathList: 207 try: 208 fileList = os.listdir( searchDir ) 209 except OSError: 210 fileList = [] 211 if infoCommand in fileList: 212 available = True 213 break 214 if available: 215 logger.debug( "Command '%s' found in directory '%s'" % \ 216 ( infoCommand, searchDir ) ) 217 else: 218 logger.debug( "Unable to find command '%s'" % infoCommand ) 219 220 if available: 221 timeleft = self.timeleft() 222 if not timeleft: 223 available = False 224 225 return available
226
227 - def isValid( self, validity = "", log = False, force_check = False ):
228 return ICredential.isValid( self, validity, log, force_check )
229
230 - def location( self ):
231 """ 232 Dummy method - returns empty string 233 """ 234 return ""
235
236 - def renew( self, validity = "", maxTry = 0, minValidity = "", check = True ):
237 return ICredential.renew( self, validity, maxTry, minValidity, check )
238
239 - def timeleft( self, units = "hh:mm:ss", force_check = False ):
240 return ICredential.timeleft( self, units, force_check = force_check )
241
242 - def timeleftInHMS( self, force_check = False ):
243 244 localTuple = time.localtime() 245 status, output, message = self.shell.cmd1( self.command.info ) 246 247 timeRemaining = "00:00:00" 248 249 if status: 250 if ( 1 + output.lower().find( "command not found" ) ): 251 logger.warning( "Command '" + self.command.info + "' not found" ) 252 logger.warning( "Unable to obtain information on AFS tokens" ) 253 timeRemaining = "" 254 255 if timeRemaining: 256 timeString = "" 257 lineList = output.split( "\n" ) 258 timeRemaining = "-1" 259 for line in lineList: 260 if ( 1 + line.lower().find( "tokens for" ) ): 261 elementList = line.rstrip( "]" ).split( "[" )[ 1 ].split() 262 if self.cell: 263 afsString = "".join( [ " afs@", self.cell, " " ] ) 264 else: 265 afsString = "afs@" 266 if not ( 1 + line.find( afsString ) ): 267 elementList = [] 268 if len( elementList ) > 1: 269 elementList.append( str( localTuple[ 0 ] ) ) 270 timeString = " ".join( elementList[ 1 : ] ) 271 timeTuple = time.strptime( timeString, "%b %d %H:%M %Y" ) 272 timeList = list( timeTuple ) 273 if localTuple[ 1 ] > timeTuple[ 1 ]: 274 timeList[ 0 ] = 1 + localTuple[ 0 ] 275 timeList[ 8 ] = localTuple[ 8 ] 276 timeTuple = tuple( timeList ) 277 timeLeft = int( time.mktime( timeTuple ) - time.time() ) 278 hours = timeLeft / ( 60 * 60 ) 279 minutes = ( timeLeft - hours * 60 * 60 ) / 60 280 seconds = timeLeft - hours * 60 * 60 - minutes * 60 281 minString = str( minutes ) 282 if len( minString ) < 2: 283 minString = "0" + minString 284 secString = str( seconds ) 285 if len( secString ) < 2: 286 secString = "0" + secString 287 timeRemaining = "%s:%s:%s" % \ 288 ( str( hours ), minString, secString ) 289 if ( timeRemaining != "-1" ): 290 break 291 292 return timeRemaining
293 294 # Add documentation strings from base class 295 for method in \ 296 [ create, destroy, isAvailable, isValid, renew, timeleft, timeleftInHMS ]: 297 if hasattr( ICredential, method.__name__ ): 298 baseMethod = getattr( ICredential, method.__name__ ) 299 setattr( method, "__doc__",\ 300 baseMethod.__doc__.replace( "credential", "AFS token" ) )
301