Revision 87d1bf2e snf-image-host/copy-monitor.py
b/snf-image-host/copy-monitor.py | ||
---|---|---|
52 | 52 |
help="The expected number of bytes to be read, " \ |
53 | 53 |
"used to compute input progress", |
54 | 54 |
default=None) |
55 |
parser.add_option("-o", "--output", dest="output", default=None, |
|
56 |
metavar="FILE", |
|
57 |
help="Write output notifications to this file") |
|
55 |
parser.add_option("-o", "--output_fd", dest="output", default=None,
|
|
56 |
metavar="FILE", type="int",
|
|
57 |
help="Write output notifications to this file descriptor")
|
|
58 | 58 |
|
59 | 59 |
(opts, args) = parser.parse_args(args) |
60 | 60 |
|
... | ... | |
95 | 95 |
|
96 | 96 |
def send_message(to, message): |
97 | 97 |
message['timestamp'] = time.time() |
98 |
to.write("%s\n" % json.dumps(message)) |
|
99 |
to.flush() |
|
98 |
os.write(to, "%s\n" % json.dumps(message)) |
|
100 | 99 |
|
101 | 100 |
|
102 | 101 |
def main(): |
103 | 102 |
(opts, args) = parse_arguments(sys.argv[1:]) |
104 |
|
|
105 |
with open(opts.output, 'w') as out: |
|
106 |
pid = os.fork() |
|
107 |
if pid == 0: |
|
108 |
# In child process: |
|
109 |
|
|
110 |
# Make sure we die with the parent and are not left behind |
|
111 |
# WARNING: This uses the prctl(2) call and is Linux-specific. |
|
112 |
prctl.set_pdeathsig(signal.SIGHUP) |
|
113 |
|
|
114 |
# exec command specified in arguments, |
|
115 |
# searching the $PATH, keeping all environment |
|
116 |
os.execvpe(args[0], args, os.environ) |
|
117 |
sys.stderr.write("execvpe failed, exiting with non-zero status") |
|
118 |
os.exit(1) |
|
119 |
|
|
120 |
# In parent process: |
|
121 |
iofname = "/proc/%d/io" % pid |
|
122 |
iof = open(iofname, "r", 0) # 0: unbuffered open |
|
123 |
sys.stderr.write("%s: created child PID = %d, monitoring file %s\n" % |
|
124 |
(sys.argv[0], pid, iofname)) |
|
125 |
|
|
126 |
message = {} |
|
127 |
message['type'] = 'copy-progress' |
|
128 |
message['total'] = opts.read_bytes |
|
129 |
|
|
130 |
while True: |
|
131 |
# check if the child process is still alive |
|
132 |
(wpid, status) = os.waitpid(pid, os.WNOHANG) |
|
133 |
if wpid == pid: |
|
134 |
report_wait_status(pid, status) |
|
135 |
if (os.WIFEXITED(status) or os.WIFSIGNALED(status)): |
|
136 |
if not (os.WIFEXITED(status) and |
|
137 |
os.WEXITSTATUS(status) == 0): |
|
138 |
return 1 |
|
139 |
else: |
|
140 |
message['position'] = message['total'] |
|
141 |
message['progress'] = float(100) |
|
142 |
send_message(out, message) |
|
143 |
return 0 |
|
144 |
|
|
145 |
iof.seek(0) |
|
146 |
for l in iof.readlines(): |
|
147 |
if l.startswith("rchar:"): |
|
148 |
message['position'] = int(l.split(': ')[1]) |
|
149 |
message['progress'] = float(100) if opts.read_bytes == 0 \ |
|
150 |
else float("%2.2f" % ( |
|
151 |
message['position'] * 100.0 / message['total'])) |
|
103 |
out = opts.output |
|
104 |
pid = os.fork() |
|
105 |
if pid == 0: |
|
106 |
# In child process: |
|
107 |
|
|
108 |
# Make sure we die with the parent and are not left behind |
|
109 |
# WARNING: This uses the prctl(2) call and is Linux-specific. |
|
110 |
prctl.set_pdeathsig(signal.SIGHUP) |
|
111 |
|
|
112 |
# exec command specified in arguments, |
|
113 |
# searching the $PATH, keeping all environment |
|
114 |
os.execvpe(args[0], args, os.environ) |
|
115 |
sys.stderr.write("execvpe failed, exiting with non-zero status") |
|
116 |
os.exit(1) |
|
117 |
|
|
118 |
# In parent process: |
|
119 |
iofname = "/proc/%d/io" % pid |
|
120 |
iof = open(iofname, "r", 0) # 0: unbuffered open |
|
121 |
sys.stderr.write("%s: created child PID = %d, monitoring file %s\n" % |
|
122 |
(sys.argv[0], pid, iofname)) |
|
123 |
|
|
124 |
message = {} |
|
125 |
message['type'] = 'copy-progress' |
|
126 |
message['total'] = opts.read_bytes |
|
127 |
|
|
128 |
while True: |
|
129 |
# check if the child process is still alive |
|
130 |
(wpid, status) = os.waitpid(pid, os.WNOHANG) |
|
131 |
if wpid == pid: |
|
132 |
report_wait_status(pid, status) |
|
133 |
if (os.WIFEXITED(status) or os.WIFSIGNALED(status)): |
|
134 |
if not (os.WIFEXITED(status) and |
|
135 |
os.WEXITSTATUS(status) == 0): |
|
136 |
return 1 |
|
137 |
else: |
|
138 |
message['position'] = message['total'] |
|
139 |
message['progress'] = float(100) |
|
152 | 140 |
send_message(out, message) |
153 |
break |
|
154 |
|
|
155 |
# Sleep for a while |
|
156 |
time.sleep(3) |
|
157 |
|
|
141 |
return 0 |
|
142 |
|
|
143 |
iof.seek(0) |
|
144 |
for l in iof.readlines(): |
|
145 |
if l.startswith("rchar:"): |
|
146 |
message['position'] = int(l.split(': ')[1]) |
|
147 |
message['progress'] = float(100) if opts.read_bytes == 0 \ |
|
148 |
else float("%2.2f" % ( |
|
149 |
message['position'] * 100.0 / message['total'])) |
|
150 |
send_message(out, message) |
|
151 |
break |
|
152 |
|
|
153 |
# Sleep for a while |
|
154 |
time.sleep(3) |
|
158 | 155 |
|
159 | 156 |
if __name__ == "__main__": |
160 | 157 |
sys.exit(main()) |
Also available in: Unified diff