def __init__(self, rssUrlList, updateDuration=1800, observers=[], log=None): self.rssUrlList = rssUrlList self.updateDuration = updateDuration self.observers = observers self.log = log self.preferences = Preferences() self.entries = {} self._StartTimer()
def main(): prefs = Preferences() registryClient = RegistryClient( 'http://www.accessgrid.org/registry/peers.txt') bridgeList = prefs.GetBridges() bridgePinger = BridgePingThread(prefs, registryClient, bridgeList.values()) bridgePinger.start() while 1: bridges = prefs.GetBridges().values() bridges.sort(lambda x, y: BridgeDescription.sort(x, y, 1)) for b in bridges: print '%2.5f %s' % (b.rank, b.name) print 'sleeping for ', bridgePinger.refreshDelay time.sleep(bridgePinger.refreshDelay)
def BuildPreferencesProxyURL(): """Build a proxy URL based on the settings in the preferences file""" from AccessGrid.Preferences import Preferences preferences = Preferences() proxyUsername = None proxyPassword = None proxyEnabled = int(preferences.GetPreference(Preferences.PROXY_ENABLED)) if not proxyEnabled: return "" if int(preferences.GetPreference(Preferences.PROXY_AUTH_ENABLED)) == 1: proxyUsername = preferences.GetPreference(Preferences.PROXY_USERNAME) proxyPassword = preferences.GetProxyPassword() return BuildProxyURL(preferences.GetPreference(Preferences.PROXY_HOST), \ preferences.GetPreference(Preferences.PROXY_PORT), \ proxyUsername, \ proxyPassword)
class AppBase: """ The application object is one of the top level objects used to build new parts of the AGTk. The application object is required to be a singleton in any process. """ # The singleton theInstance = None # The class method for retrieving/creating the singleton def instance(): """ The interface for getting the one true instance of this object. """ return AppBase.theInstance instance = staticmethod(instance) def set_instance(obj): AppBase.theInstance = obj set_instance = staticmethod(set_instance) # The real constructor def __init__(self): """ The application constructor that enforces the singleton pattern. """ if AppBase.instance(): raise Exception, "Only one instance of AppBase is allowed; already have instance of %s" % ( AppBase.instance().__class__, ) AppBase.set_instance(self) self.parser = OptionParser() self.parser.add_option("-d", "--debug", action="store_true", dest="debug", default=0, help="Set the debug level of this program.") self.parser.add_option("-l", "--logfile", dest="logfilename", metavar="LOGFILE", default=None, help="Specify a log file to output logging to.") self.parser.add_option( "--numlogfiles", dest="numlogfiles", metavar="NUMLOGFILES", default=1, type="int", help="Specify the number of log files to retain") self.parser.add_option("--logfilesize", dest="logfilesize", metavar="LOGFILESIZE", default=10000000, type="long", help="Specify the size of log files to retain") self.parser.add_option( "-c", "--configfile", dest="configfilename", metavar="CONFIGFILE", default=None, help="Specify a configuration file for the program.") self.parser.add_option( "--version", action="store_true", dest="version", default=0, help="Print out what version of the toolkit this is.") self.parser.add_option("--secure", type="int", dest="secure", default=0, help="Specify whether the service uses SSL.") self.parser.add_option("--cert", dest="cert", metavar="CERTFILE", default=None, help="Specify a certificate file to use.") self.parser.add_option("--key", dest="key", metavar="KEYFILE", default=None, help="Specify a certificate key file to use.") self.parser.add_option( "--cadir", dest="cadir", metavar="CADIR", default=None, help="Specify the directory containing CA certificates.") self.options = None self.userConfig = None self.agtkConfig = None self.systemConfig = SystemConfig.instance() self.log = None self.loggerLevels = None self.fhLoggerLevels = None self._certificateManager = None self._certMgrUI = None # This initializes logging self.log = Log.GetLogger(Log.Toolkit) self.log.debug("Initializing AG Toolkit version %s %s", GetVersion(), GetStatus()) self.log.info("Command and arguments: %s" % sys.argv) self.__context = None self.__passphrase = None # This method implements the initialization strategy outlined # in AGEP-0112 def Initialize(self, name=None, args=None): """ This method sets up everything for reasonable execution. At the first sign of any problems it raises exceptions and exits. """ self.name = name # 1. Process Command Line Arguments argvResult = self.ProcessArgs(args=args) # 2. Load the Toolkit wide configuration. try: self.agtkConfig = AGTkConfig.instance(0) except Exception: self.log.exception("Toolkit Initialization failed.") sys.exit(-1) # 3. Load the user configuration, creating one if necessary. try: self.userConfig = UserConfig.instance(initIfNeeded=1) except Exception: self.log.exception("User Initialization failed.") sys.exit(-1) # Load client preferences self.preferences = Preferences() self.ProcessArgsThatUsePreferences() # 4. Redirect logging to files in the user's directory, # purging memory to file fh = Log.defLogHandler if self.options.logfilename is not None: if not self.options.logfilename.endswith(".log"): self.name = self.options.logfilename + ".log" else: self.name = self.options.logfilename elif self.name is not None: if not self.name.endswith(".log"): self.name = self.name + ".log" self.log.info("Logfile Name: %s", self.name) if self.name: if not self.name.startswith(os.sep) \ and not self.name.startswith("."): filename = os.path.join(self.userConfig.GetLogDir(), self.name) else: filename = self.name fh = Log.RotatingFileHandler(filename, "a", self.options.logfilesize, self.options.numlogfiles) fh.setFormatter(Log.GetFormatter()) self.fhLoggerLevels = Log.HandleLoggers(fh, Log.GetDefaultLoggers()) self.fhLoggerLevels.SetLevel(Log.DEBUG) self.fhLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor) self.loggerLevels = self.fhLoggerLevels # Send the log in memory to stream (debug) or file handler. if self.options.debug or int( self.preferences.GetPreference(Preferences.LOG_TO_CMD)): Log.mlh.setTarget(Log.defStreamHandler) else: Log.mlh.setTarget(fh) Log.mlh.close() Log.RemoveLoggerLevels(Log.memLevels, Log.GetLoggers()) self.__SetLogPreference() self.CheckDependencies() # Check if machine clock is synchronized. # - Disabled for 3.0: clock-sync is important when using proxy certs, which we're not #self.__CheckForInvalidClock() self.__context = None return argvResult def CheckDependencies(self): if not hasattr(socket, 'ssl'): raise MissingDependencyError("SSL") def GetContext(self): # Hack to allow use of proxy certs, until the necessary # interface is exposed through M2Crypto os.environ['OPENSSL_ALLOW_PROXY_CERTS'] = '1' certManager = self.GetCertificateManager() caDir = self._certificateManager.caDir """ Logic here is like so: If we haven't created a context - create one If the default identity has an encrypted private key - If a valid proxy certificate exists - If the current context is not using the proxy cert - Make it so - Else - Create a proxy certificate - Configure the context to use the proxy certificate Else - If the current context is not using the default certificate - Make it so """ # Create the SSL context if needed if not self.__context: self.__context = SSL.Context('sslv23') self.__context.load_verify_locations(capath=caDir) #self.__context.set_verify(SSL.verify_peer,10,self.VerifyCallback) self.__context.set_verify(SSL.verify_peer, 10) self.__context.set_session_id_ctx('127.0.0.1:8006') self.__context.set_cipher_list('LOW:TLSv1:@STRENGTH') # if the private key is encrypted, we need a proxy certificate id = self.GetCertificateManager().GetDefaultIdentity() if id.HasEncryptedPrivateKey(): # - if a valid proxy does exists, confirm that it's being used if certManager.HaveValidProxy(): # Should confirm that proxy is being used by context; # for now, just force it to be used id = certManager.GetProxyCert() self.log.info('Using proxy certificate: %s %s', id.GetPath(), id.GetKeyPath()) self.__context.load_cert_chain(id.GetPath(), id.GetKeyPath()) else: # create a proxy and use it certManager.CreateProxyCertificate() id = certManager.GetProxyCert() self.log.info('Using proxy certificate: %s %s', id.GetPath(), id.GetKeyPath()) self.__context.load_cert_chain(id.GetPath(), id.GetKeyPath()) else: # Should confirm that certificate is being used by context; # for now, just force it to be used self.log.info('Using unencrypted certificate: %s %s', id.GetPath(), id.GetKeyPath()) self.__context.load_cert(id.GetPath(), id.GetKeyPath()) return self.__context def VerifyCallback(self, ok, store): # unused, except possibly for debugging self.log.info('VerifyCallback: ok,store=%d %s %s' % (ok, store.get_current_cert().get_subject().as_text(), store.get_error())) return 1 def __SetLogPreference(self): """ Set correct log level for each log category according to preferences. """ logFiles = Log.GetCategories() for name in logFiles: # Get level from preferences. logLevel = int(self.preferences.GetPreference(name)) fLevels = self.GetFileLogLevels() sLevels = self.GetStreamLogLevels() # Level for files if fLevels: fLevels.SetLevel(logLevel, name) # Level for streams if sLevels: sLevels.SetLevel(logLevel, name) def __CheckForInvalidClock(self): """ Check to see if the local clock is out of synch, a common reason for a failed authentication. This routine loggs a warningString. """ timeserver = "ntp-1.accessgrid.org" timeout = 0.3 maxOffset = 10 try: serverTime = GetSNTPTime(timeserver, timeout) except: self.log.exception( "Toolkit.__CheckForValidClock: Connection to sntp server at %s failed", timeserver) serverTime = None if serverTime is not None: diff = int(time.time() - serverTime) absdiff = abs(diff) if absdiff > maxOffset: if diff > 0: direction = "fast" else: direction = "slow" warningString = ("The machine clock is incorrect on\n" + \ "your computer: it is %s seconds %s with respect\n" + \ "to the time server at %s.") % \ (absdiff, direction, timeserver) self.log.warn("Toolkit.__CheckForValidClock: %s" % warningString) def ProcessArgs(self, args=None): """ Process toolkit wide standard arguments. Then return the modified argv so the app can choose to parse more if it requires that. """ if args == None: (self.options, ret_args) = self.parser.parse_args() else: (self.options, ret_args) = self.parser.parse_args(args=args) if self.options.version: print "Access Grid Toolkit Version: ", GetVersion() sys.exit(0) if self.options.cert: self.options.secure = 1 return ret_args def ProcessArgsThatUsePreferences(self): """ Process toolkit wide logging arguments. Then return the modified argv so the app can choose to parse more if it requires that. """ if self.options.debug or int( self.preferences.GetPreference(Preferences.LOG_TO_CMD)): self.streamLoggerLevels = Log.HandleLoggers( Log.defStreamHandler, Log.GetDefaultLoggers()) self.streamLoggerLevels.SetLevel(Log.DEBUG) self.streamLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor) # When in debug mode, we'll make the stream the primary handler. self.loggerLevels = self.streamLoggerLevels else: # If not in debug, we only used the StreamHandler before Logging was initialized. # so we don't have a StreamLoggerLevels. self.streamLoggerLevels = None def AddCmdLineOption(self, option): self.parser.add_option(option) def SetCmdLineDefault(self, option, value): if self.parser.defaults.has_key(option): self.parser.defaults[option] = value else: self.log.error('SetCmdLineDefault called with invalid option: %s', option) def GetPreferences(self): ''' Get client preferences. ''' return self.preferences def SetPreferences(self, preferences): ''' Set preferences and save them to configuration file. ''' self.preferences = preferences self.preferences.StorePreferences() def GetOption(self, arg): if hasattr(self.options, arg): return getattr(self.options, arg) else: return None def GetDebugLevel(self): """ """ return self.GetOption("debug") def GetLogFilename(self): """ """ return self.GetOption("logfilename") def GetConfigFilename(self): """ """ return self.GetOption("configfilename") def GetLog(self): """ Return a toolkit wide log. """ return self.log def GetLogLevels(self): """ Return the primary loggingLevels object. in debug mode: self.streamLoggerLevels otherwise: self.fhLoggerLevels Should be called after initialization. Levels can be set like this: ll = GetFileLevels() ll.SetLevel(Log.DEBUG) and tuned like this: ll.SetLevel(Log.WARN, Log.Hosting) """ return self.loggerLevels def GetFileLogLevels(self): """ Return the loggingLevels object for the current log file. """ return self.fhLoggerLevels def GetStreamLogLevels(self): """ Return the loggingLevels object for the current output stream. Returns None when not in debug mode. """ return self.streamLoggerLevels def GetToolkitConfig(self): return self.agtkConfig def GetUserConfig(self): return self.userConfig def GetDefaultSubject(self): try: ident = self.GetCertificateManager().GetDefaultIdentity() except CertificateManager.NoCertificates: ident = None if ident is not None: from AccessGrid.Security import X509Subject subject = X509Subject.CreateSubjectFromString( str(ident.GetSubject())) else: subject = None return subject def GetCertificateManager(self): if self._certificateManager == None: if self.userConfig == None: raise Exception( "No user config dir, Toolkit may not be initialized.") configDir = self.userConfig.GetConfigDir() self._certificateManager = CertificateManager.CertificateManager( configDir) self.log.info("Initialized certificate manager.") self._certificateManager.InitEnvironment() return self._certificateManager def GetCertificateManagerUI(self): if self._certMgrUI == None: # 5. Initialize Certificate Management # This has to be done by sub-classes from AccessGrid.Security import CertificateManager self._certMgrUI = CertificateManager.CertificateManagerUserInterface( self.GetCertificateManager()) # 6. Do one final check, if we don't have a default # Identity we warn them, but they can still request certs. # self._certMgrUI.InitEnvironment() if self.GetDefaultSubject() is None: self.log.error("Toolkit initialized with no default identity.") self.log.info("Initialized certificate manager UI.") return self._certMgrUI def GetHostname(self): return self.systemConfig.GetHostname() def FindConfigFile(self, configFile): """ Locate given file in configuration directories: first check user dir, then system dir; return None if not found """ if self.userConfig is None: self.userConfig = UserConfig.instance() pathToFile = os.path.join(self.userConfig.GetConfigDir(), configFile) self.log.debug("Looking for: %s", pathToFile) if os.path.exists(pathToFile): return pathToFile pathToFile = os.path.join(self.agtkConfig.GetConfigDir(), configFile) self.log.debug("Looking for: %s", pathToFile) if os.path.exists(pathToFile): return pathToFile raise Exception, "File Not Found"
def Initialize(self, name=None, args=None): """ This method sets up everything for reasonable execution. At the first sign of any problems it raises exceptions and exits. """ self.name = name # 1. Process Command Line Arguments argvResult = self.ProcessArgs(args=args) # 2. Load the Toolkit wide configuration. try: self.agtkConfig = AGTkConfig.instance(0) except Exception: self.log.exception("Toolkit Initialization failed.") sys.exit(-1) # 3. Load the user configuration, creating one if necessary. try: self.userConfig = UserConfig.instance(initIfNeeded=1) except Exception: self.log.exception("User Initialization failed.") sys.exit(-1) # Load client preferences self.preferences = Preferences() self.ProcessArgsThatUsePreferences() # 4. Redirect logging to files in the user's directory, # purging memory to file fh = Log.defLogHandler if self.options.logfilename is not None: if not self.options.logfilename.endswith(".log"): self.name = self.options.logfilename + ".log" else: self.name = self.options.logfilename elif self.name is not None: if not self.name.endswith(".log"): self.name = self.name + ".log" self.log.info("Logfile Name: %s", self.name) if self.name: if not self.name.startswith(os.sep) \ and not self.name.startswith("."): filename = os.path.join(self.userConfig.GetLogDir(), self.name) else: filename = self.name fh = Log.RotatingFileHandler(filename, "a", self.options.logfilesize, self.options.numlogfiles) fh.setFormatter(Log.GetFormatter()) self.fhLoggerLevels = Log.HandleLoggers(fh, Log.GetDefaultLoggers()) self.fhLoggerLevels.SetLevel(Log.DEBUG) self.fhLoggerLevels.SetLevel(Log.CRITICAL, Log.RTPSensor) self.loggerLevels = self.fhLoggerLevels # Send the log in memory to stream (debug) or file handler. if self.options.debug or int( self.preferences.GetPreference(Preferences.LOG_TO_CMD)): Log.mlh.setTarget(Log.defStreamHandler) else: Log.mlh.setTarget(fh) Log.mlh.close() Log.RemoveLoggerLevels(Log.memLevels, Log.GetLoggers()) self.__SetLogPreference() self.CheckDependencies() # Check if machine clock is synchronized. # - Disabled for 3.0: clock-sync is important when using proxy certs, which we're not #self.__CheckForInvalidClock() self.__context = None return argvResult
class RssReader: """ RssReader takes a list of RSS urls which it should watch, updating when the specified duration has expired. RssReader accepts registration of observers, which will be updated with calls to the following methods: Update Error """ def __init__(self, rssUrlList, updateDuration=1800, observers=[], log=None): self.rssUrlList = rssUrlList self.updateDuration = updateDuration self.observers = observers self.log = log self.preferences = Preferences() self.entries = {} self._StartTimer() def Synch(self): for rssUrl in self.rssUrlList: self._ProcessUrl(rssUrl) def _ProcessUrl(self, rssUrl): if self.log: self.log.debug('Retrieving rss: %s', rssUrl) if rssUrl.startswith("file://"): rssFile = rssUrl[7:] d = feedparser.parse(rssFile) else: proxyEnabled = int( self.preferences.GetPreference(Preferences.PROXY_ENABLED)) if proxyEnabled: proxy = urllib2.ProxyHandler( {"http": Utilities.BuildPreferencesProxyURL()}) d = feedparser.parse(rssUrl, handlers=[proxy]) else: d = feedparser.parse(rssUrl) try: channelTime = d['feed']['modified'] print 'channelTime = ', channelTime docDate = strtimeToSecs(channelTime) except KeyError: docDate = 0 store = 0 if rssUrl in self.entries.keys(): lastDocDate = self.entries[rssUrl][1] if lastDocDate < docDate or docDate == 0: # document has been updated; store it store = 1 else: # new document; store it store = 1 if store: if self.log: self.log.debug('Storing rss: %s', rssUrl) self.entries[rssUrl] = (d, docDate) # Update observers map(lambda o: o.UpdateRss(rssUrl, d, docDate), self.observers) def SetUpdateDuration(self, updateDuration): wereEqual = (self.updateDuration == updateDuration) self.updateDuration = updateDuration if not wereEqual: self._RestartTimer() def _RestartTimer(self): self.timer.cancel() self._StartTimer() def _StartTimer(self): if self.updateDuration > 0: self.timer = threading.Timer(self.updateDuration, self._TimedUpdate) self.timer.start() def _TimedUpdate(self): try: self.Synch() except Exception, e: print 'exception updating feed:', e if self.updateDuration > 0: self.timer = threading.Timer(self.updateDuration, self._TimedUpdate) self.timer.start()
def OpenURL(url): """ This is a proxy-agnostic way of opening a URL and retrieving the response. The proxy settings are extracted from the preferences. If the connection fails, a dialog is opened to query the user for their username and password. This means users do not have to store their password in the preferences file, which is insecure to a determined attacker. """ from AccessGrid.Preferences import Preferences from AccessGrid.UIUtilities import ProxyAuthDialog ID_OK = 5100 # hard-coding this for now to avoid importing wx preferences = Preferences() if int(preferences.GetPreference(Preferences.PROXY_ENABLED)): # There is a proxy set, so build the URL of the proxy proxySupport = urllib2.ProxyHandler( {"http": BuildPreferencesProxyURL()}) opener = urllib2.build_opener(proxySupport, urllib2.HTTPHandler) urllib2.install_opener(opener) try: response = urllib2.urlopen(url) except urllib2.URLError, e: errorCode = 0 # URLError is the superclass of HTTPError, which will return an error # code. URLError *won't*, so that has to be extracted with a regex if hasattr(e, 'code'): errorCode = int(e.code) elif hasattr(e, 'reason'): # This is a URLError, so extract the error code from reason. result = re.search("^\((\d+)", str(e.reason)) errorCode = int(result.group(1)) log.debug("URLlib failed: " + str(e.reason)) # Technically only 407 should come up from a proxy authentication # failure if errorCode == 407: log.info("Proxy authentication failed for: " + url) # Only show the dialog if an authenticated proxy was enabled if int(preferences.GetPreference( Preferences.PROXY_AUTH_ENABLED)) == 1: dialog = ProxyAuthDialog( None, -1, "Check proxy authentication settings") dialog.SetProxyUsername( preferences.GetPreference(Preferences.PROXY_USERNAME)) dialog.SetProxyPassword(preferences.GetProxyPassword()) dialog.SetProxyEnabled( int( preferences.GetPreference( Preferences.PROXY_AUTH_ENABLED))) if dialog.ShowModal() == ID_OK: preferences.SetPreference(Preferences.PROXY_ENABLED, 1) preferences.SetPreference(Preferences.PROXY_USERNAME, dialog.GetProxyUsername()) preferences.SetProxyPassword(dialog.GetProxyPassword()) preferences.SetPreference(Preferences.PROXY_AUTH_ENABLED, dialog.GetProxyEnabled()) preferences.StorePreferences() # Try again return OpenURL(url) elif hasattr(e, 'reason'): log.debug("URLlib failed: " + str(e.reason)) response = None