Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

#!/usr/bin/env python 

 

""" 

@file ion/core/ioninit.py 

@author Michael Meisinger 

@brief definitions and code that needs to run for any use of ion 

""" 

 

import logging 

import logging.config 

import logging.handlers 

import re 

import os, os.path 

 

 

from ion.util.context import ConversationContext 

from ion.util.path import adjust_dir 

from ion.core import ionconst as ic 

from ion.util.config import Config 

 

#print "ION (Integrated Observatory Network) core packages initializing (ver. %s)" % (ic.VERSION) 

 

# ION has a minimum required python version 

import sys 

if not hasattr(sys, "version_info") or sys.version_info < (2,5): 

    raise RuntimeError("ioncore requires Python 2.5 or later.") 

if sys.version_info > (3,0): 

    raise RuntimeError("ioncore is not compatible with Python 3.0 or later.") 

 

# The following code looking for a ION_ALTERNATE_LOGGING_CONF environment 

# variable can go away with the new ion environment directories  

 

# Configure logging system (console, logfile, other loggers) 

# NOTE: Console logging is appended to Twisted log output prefix!! 

logconf = adjust_dir(ic.LOGCONF_FILENAME) 

if os.environ.has_key(ic.ION_ALTERNATE_LOGGING_CONF): 

    # make sure that path exists 

    altpath = adjust_dir(os.environ.get(ic.ION_ALTERNATE_LOGGING_CONF)) 

    if os.path.exists(altpath): 

        logconf = altpath 

    else: 

        print "Warning: ION_ALTERNATE_LOGGING_CONF specified (%s), but not found" % altpath 

 

logging.config.fileConfig(logconf) 

 

# Load configuration properties for any module to access 

ion_config = Config(ic.ION_CONF_FILENAME) 

 

# Update configuration with local override config 

ion_config.update_from_file(ic.ION_LOCAL_CONF_FILENAME) 

 

# Arguments given to the container (i.e. the python process executing this code) 

cont_args = {} 

 

# Always refers to current container singleton instance, once first initialized 

container_instance = None 

 

# The name shared by all containers of one system (i.e. cluster name) 

sys_name = None 

 

# Global flag determining whether currently running unit test 

testing = True 

 

# Optionally use Loggly for logging, just an experiment for now 

loggly_key = ion_config.getValue2(__name__, 'loggly_key', None) 

loggly_key = os.environ.get('LOGGLY_KEY', loggly_key) 

if loggly_key is not None: 

    import hoover 

    import httplib2 

 

    # Need to monkey-patch to bypass SSL validation :( 

    _post_to_endpoint = hoover.utils.post_to_endpoint 

    def post_to_endpoint(endpoint, message): 

        h = httplib2.Http(disable_ssl_certificate_validation=True) 

        headers = {'connection': 'close'} 

        h.request(endpoint, 'POST', message, headers=headers) 

    async_post_to_endpoint = hoover.utils.async(post_to_endpoint) 

    setattr(hoover.utils, 'post_to_endpoint', post_to_endpoint) 

    setattr(hoover.utils, 'async_post_to_endpoint', async_post_to_endpoint) 

    setattr(hoover.handlers, 'async_post_to_endpoint', async_post_to_endpoint) 

 

    # Override the log method to add hostname in front 

    import platform 

    hostname = platform.node() 

    class IonLogglyHandler(hoover.LogglyHttpHandler): 

        def emit(self, record): 

            try: 

                setattr(record, 'hostname', hostname) 

                hoover.LogglyHttpHandler.emit(self, record) 

 

            except (KeyboardInterrupt, SystemExit): 

                raise 

            except Exception, ex: 

                print >> sys.stderr, "ERROR during logging to loggly: %s " % str(ex) 

                self.handleError(record) 

 

    loggly_handler = IonLogglyHandler(token=loggly_key) 

    loggly_handler.setLevel(logging.WARNING) 

    loggly_formatter = logging.Formatter( 

        '%(hostname)s #%(process)s> %(asctime)s.%(msecs)03d [%(levelname)s] {%(module)s:%(lineno)3d} %(message)s') 

    loggly_handler.setFormatter(loggly_formatter) 

    logging.root.addHandler(loggly_handler) 

 

def config(name): 

    """ 

    Get a subtree of the global configuration, typically for a module 

    """ 

    return Config(name, ion_config) 

 

def get_config(confname, conf=None): 

    """ 

    Returns a Config instance referenced by the file name in the system config's 

    entry 

    @param confname  entry in the conf configuration 

    @param conf None for system config or different config 

    """ 

    if conf == None: 

        conf = ion_config 

    return Config(conf.getValue(confname)).getObject() 

 

def install_msgpacker(): 

    from ion.core.messaging.serialization import registry 

    import msgpack 

    registry.register('msgpack', msgpack.packb, msgpack.unpackb, content_type='application/msgpack', content_encoding='binary') 

    registry._set_default_serializer('msgpack') 

 

install_msgpacker() 

 

def set_log_levels(levelfilekey=None): 

    """ 

    Sets logging levels of per module loggers to given values. Loggers of 

    packages are higher in the chain of module specific loggers. 

    If called with None argument, will read the global and local files with 

    log levels. Otherwise, read the file indicated by filename and if it exists, 

    set the log levels as given. 

    """ 

    if levelfilekey == None: 

        set_log_levels('loglevels') 

        set_log_levels('loglevelslocal') 

    else: 

        levellistkey = ion_config.getValue2(__name__, levelfilekey, None) 

        levellist = None 

        try: 

            filecontent = open(adjust_dir(levellistkey),).read() 

            # Eval file content in the namespace of the logging module, such 

            # that constants like DEBUG are resolved correctly 

            levellist = eval(filecontent, logging.__dict__) 

        except IOError, ioe: 

            pass 

        except Exception, ex: 

            print ex 

        if not levellist: 

            return 

        assert type(levellist) is list 

        for level in levellist: 

            logging.getLogger(level[0]).setLevel(level[1]) 

 

set_log_levels() 

 

#def augment_logging(): 

#    """ 

#    HACK: Replace the getLogger function in the logging module, such that it 

#    adds a Log 

#    """ 

#    from ion.util import ionlogging 

#    getlogger = logging.getLogger 

#    def ion_getLogger(loggername, *args, **kwargs): 

#        logger = getlogger(loggername, *args, **kwargs) 

#        ladapter = ionlogging.LoggerAdapter(logger, ionlogging.ProcessInfo()) 

#        return ladapter 

#    logging.getLogger = ion_getLogger 

# 

#augment_logging() 

 

# HACKHACK: Putz with Twisted's twisted.python.log facility 

# The goal is to get rid of the prefix in each line before the message 

def clean_twisted_logging(): 

    from twisted.python import log, util 

    obs0 = log.theLogPublisher.observers[0] 

    ro = log.removeObserver 

    if not hasattr(obs0.im_self,'write'): 

        # In case of trial testcases this hack does not work. 

        return 

    fdwrite = obs0.im_self.write 

    fdflush = obs0.im_self.flush 

    def log_emit(eventDict): 

        text = log.textFromEventDict(eventDict) 

        if text is None: 

            return 

        util.untilConcludes(fdwrite, text + "\n") 

        util.untilConcludes(fdflush) 

    def remove_nop(obs): 

        if obs != obs0: 

            ro(obs) 

    log.theLogPublisher.removeObserver(obs0) 

    log.theLogPublisher.addObserver(log_emit) 

    log.removeObserver = remove_nop 

 

clean_twisted_logging() 

 

 

# SIGQUIT stack trace based on: 

# http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application/133384#133384 

import code, traceback, signal 

def debug(sig, frame): 

    d = {'_frame':frame} 

    d.update(frame.f_globals) 

    d.update(frame.f_locals) 

 

    i = code.InteractiveConsole(d) 

    message  = "Signal recieved : entering python shell.\nTraceback:\n" 

    message += ''.join(traceback.format_stack(frame)) 

    i.interact(message) 

 

try: 

    signal.signal(signal.SIGQUIT, debug)  # Register handler 

except ValueError, ex: 

    # You're on Windows, no fancy debugging for you!! 

    pass 

 

def shutdown_or_die(delay_sec=0): 

    """ Wait the given number of seconds and forcibly kill this process if it's still running. """ 

 

    def diediedie(sig=None, frame=None): 

        pid = os.getpid() 

        print 'Container did not shutdown correctly. Forcibly terminating with SIGKILL (pid %d).' % (pid) 

        os.kill(pid, signal.SIGKILL) 

 

    if delay_sec > 0: 

        try: 

            old = signal.signal(signal.SIGALRM, diediedie) 

            signal.alarm(delay_sec) 

 

            if old: 

                print 'Warning: shutdown_or_die found a previously registered ALARM and overrode it.' 

        except ValueError, ex: 

            print 'Failed to set failsafe shutdown signal. This only works on UNIX platforms.' 

            pass 

    else: 

        diediedie()