Project

General

Profile

condorExe.py

Igor Sfiligoi, 10/04/2012 04:08 PM

 
1
#
2
# Project:
3
#   glideinWMS
4
#
5
# File Version:
6
#
7
# Description:
8
#   This module implements the functions to execute condor commands
9
#
10
# Author:
11
#   Igor Sfiligoi (Sept 7th 2006)
12
#
13

    
14

    
15
import os
16
import os.path
17
import popen2
18
import string
19
import select
20
import cStringIO
21
import fcntl
22
import time
23

    
24
class UnconfigError(RuntimeError):
25
    def __init__(self,str):
26
        RuntimeError.__init__(self,str)
27

    
28
class ExeError(RuntimeError):
29
    def __init__(self,str):
30
        RuntimeError.__init__(self,str)
31

    
32
#
33
# Configuration
34
#
35

    
36
# Set path to condor binaries, if needed
37
def set_path(new_condor_bin_path,new_condor_sbin_path=None):
38
    global condor_bin_path,condor_sbin_path
39
    condor_bin_path=new_condor_bin_path
40
    if new_condor_sbin_path!=None:
41
        condor_sbin_path=new_condor_sbin_path
42

    
43
#
44
# Execute an arbitrary condor command and return its output as a list of lines
45
#  condor_exe uses a relative path to $CONDOR_BIN
46
# Fails if stderr is not empty
47
#
48

    
49
# can throw UnconfigError or ExeError
50
def exe_cmd(condor_exe,args,stdin_data=None,env={}):
51
    global condor_bin_path
52

    
53
    if condor_bin_path==None:
54
        raise UnconfigError, "condor_bin_path is undefined!"
55
    condor_exe_path=os.path.join(condor_bin_path,condor_exe)
56

    
57
    cmd="%s %s" % (condor_exe_path,args)
58

    
59
    return iexe_cmd(cmd,stdin_data,env)
60

    
61
def exe_cmd_sbin(condor_exe,args,stdin_data=None,env={}):
62
    global condor_sbin_path
63

    
64
    if condor_sbin_path==None:
65
        raise UnconfigError, "condor_sbin_path is undefined!"
66
    condor_exe_path=os.path.join(condor_sbin_path,condor_exe)
67

    
68
    cmd="%s %s" % (condor_exe_path,args)
69

    
70
    return iexe_cmd(cmd,stdin_data,env)
71

    
72
############################################################
73
#
74
# P R I V A T E, do not use
75
#
76
############################################################
77

    
78
# can throw ExeError
79
def iexe_cmd(cmd, stdin_data=None,env={}):
80
    """Fork a process and execute cmd - rewritten to use select to avoid filling
81
    up stderr and stdout queues.
82

83
    @type cmd: string
84
    @param cmd: Sting containing the entire command including all arguments
85
    @type stdin_data: string
86
    @param stdin_data: Data that will be fed to the command via stdin
87
    @type env: dict
88
    @param env: Environment to be set before execution
89
    """
90
    output_lines = None
91
    error_lines = None
92
    exitStatus = 0
93
    try:
94
        saved_env={}
95
        try:
96
            # save and set the environment
97
            for k in env.keys():
98
                if os.environ.has_key(k):
99
                    saved_env[k]=os.environ[k]
100
                    if env[k]==None:
101
                        del os.environ[k]
102
                else:
103
                    saved_env[k]=None
104
                if env[k]!=None:
105
                    os.environ[k]=env[k]
106

    
107
            # launch process
108
            print "%i about to popen %s"%(os.getpid(),cmd)
109
            child = popen2.Popen3(cmd, capturestderr=True)
110
            print "%i done popen %s"%(os.getpid(),cmd)
111
        finally:
112
            # restore the environemnt
113
            for k in saved_env.keys():
114
                if saved_env[k]==None:
115
                    del os.environ[k]
116
                else:
117
                    os.environ[k]=saved_env[k]
118
            
119
        if stdin_data != None:
120
            child.tochild.write(stdin_data)
121

    
122
        child.tochild.close()
123

    
124
        stdout = child.fromchild
125
        stderr = child.childerr
126

    
127
        outfd = stdout.fileno()
128
        errfd = stderr.fileno()
129

    
130
        outeof = erreof = 0
131
        outdata = cStringIO.StringIO()
132
        errdata = cStringIO.StringIO()
133

    
134
        fdlist = [outfd, errfd]
135
        for fd in fdlist: # make stdout/stderr nonblocking
136
            fl = fcntl.fcntl(fd, fcntl.F_GETFL)
137
            fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
138

    
139
        print "%i before while"%os.getpid()
140
        while fdlist:
141
            time.sleep(.001) # prevent 100% CPU spin
142
            ready = select.select(fdlist, [], [])
143
            if outfd in ready[0]:
144
                outchunk = stdout.read()
145
                if outchunk == '':
146
                    fdlist.remove(outfd)
147
                else:
148
                    outdata.write(outchunk)
149

    
150
            if errfd in ready[0]:
151
                errchunk = stderr.read()
152
                if errchunk == '':
153
                    fdlist.remove(errfd)
154
                else:
155
                    errdata.write(errchunk)
156

    
157
        print "%i after while"%os.getpid()
158
        exitStatus = child.wait()
159
        outdata.seek(0)
160
        errdata.seek(0)
161
        output_lines = outdata.readlines()
162
        error_lines = errdata.readlines()
163

    
164
    except Exception, ex:
165
        raise ExeError, "%i Unexpected Error running '%s'\nStdout:%s\nStderr:%s\n" \
166
            "Exception OSError: %s" % (os.getpid(),cmd, str(output_lines), str(error_lines), ex)
167

    
168
    print "%i about to exit"%os.getpid()
169
    if exitStatus:
170
        raise ExeError, "%i Error running '%s'\ncode %i:%s" % (os.getpid(),cmd, os.WEXITSTATUS(exitStatus), "".join(error_lines))
171

    
172
    return output_lines
173

    
174

    
175
#
176
# Set condor_bin_path
177
#
178

    
179
def init1():
180
    global condor_bin_path
181
    condor_bin_path='/usr/local/glidecondor/bin'
182
    return
183
    # try using condor commands to find it out
184
    try:
185
        condor_bin_path=iexe_cmd("condor_config_val BIN")[0][:-1] # remove trailing newline
186
    except ExeError,e:
187
        print "Failed init1"
188
        # try to find the RELEASE_DIR, and append bin
189
        try:
190
            release_path=iexe_cmd("condor_config_val RELEASE_DIR")
191
            condor_bin_path=os.path.join(release_path[0][:-1],"bin")
192
        except ExeError,e:
193
            # try condor_q in the path
194
            try:
195
                condorq_bin_path=iexe_cmd("which condor_q")
196
                condor_bin_path=os.path.dirname(condorq_bin_path[0][:-1])
197
            except ExeError,e:
198
                # look for condor_config in /etc
199
                if os.environ.has_key("CONDOR_CONFIG"):
200
                    condor_config=os.environ["CONDOR_CONFIG"]
201
                else:
202
                    condor_config="/etc/condor/condor_config"
203

    
204
                try:
205
                    # BIN = <path>
206
                    bin_def=iexe_cmd('grep "^ *BIN" %s'%condor_config)
207
                    condor_bin_path=string.split(bin_def[0][:-1])[2]
208
                except ExeError, e:
209
                    try:
210
                        # RELEASE_DIR = <path>
211
                        release_def=iexe_cmd('grep "^ *RELEASE_DIR" %s'%condor_config)
212
                        condor_bin_path=os.path.join(string.split(release_def[0][:-1])[2],"bin")
213
                    except ExeError, e:
214
                        pass # don't know what else to try
215

    
216
#
217
# Set condor_sbin_path
218
#
219

    
220
def init2():
221
    global condor_sbin_path
222
    condor_sbin_path='/usr/local/glidecondor/sbin'
223
    return
224
    # try using condor commands to find it out
225
    try:
226
        condor_sbin_path=iexe_cmd("condor_config_val SBIN")[0][:-1] # remove trailing newline
227
    except ExeError,e:
228
        print "Failed init2"
229
        # try to find the RELEASE_DIR, and append bin
230
        try:
231
            release_path=iexe_cmd("condor_config_val RELEASE_DIR")
232
            condor_sbin_path=os.path.join(release_path[0][:-1],"sbin")
233
        except ExeError,e:
234
            # try condor_q in the path
235
            try:
236
                condora_sbin_path=iexe_cmd("which condor_advertise")
237
                condor_sbin_path=os.path.dirname(condora_sbin_path[0][:-1])
238
            except ExeError,e:
239
                # look for condor_config in /etc
240
                if os.environ.has_key("CONDOR_CONFIG"):
241
                    condor_config=os.environ["CONDOR_CONFIG"]
242
                else:
243
                    condor_config="/etc/condor/condor_config"
244

    
245
                try:
246
                    # BIN = <path>
247
                    bin_def=iexe_cmd('grep "^ *SBIN" %s'%condor_config)
248
                    condor_sbin_path=string.split(bin_def[0][:-1])[2]
249
                except ExeError, e:
250
                    try:
251
                        # RELEASE_DIR = <path>
252
                        release_def=iexe_cmd('grep "^ *RELEASE_DIR" %s'%condor_config)
253
                        condor_sbin_path=os.path.join(string.split(release_def[0][:-1])[2],"sbin")
254
                    except ExeError, e:
255
                        pass # don't know what else to try
256

    
257
def init():
258
    init1()
259
    init2()
260

    
261
# This way we know that it is undefined
262
condor_bin_path=None
263
condor_sbin_path=None
264

    
265
init()
266

    
267

    
268