Revision 1a2e7fe9 lib/masterd/instance.py
b/lib/masterd/instance.py | ||
---|---|---|
50 | 50 |
#: Time after which daemon must be listening |
51 | 51 |
DEFAULT_LISTEN_TIMEOUT = 10 |
52 | 52 |
|
53 |
#: Progress update interval |
|
54 |
DEFAULT_PROGRESS_INTERVAL = 60 |
|
55 |
|
|
53 | 56 |
__slots__ = [ |
54 | 57 |
"error", |
55 | 58 |
"ready", |
56 | 59 |
"listen", |
57 | 60 |
"connect", |
61 |
"progress", |
|
58 | 62 |
] |
59 | 63 |
|
60 | 64 |
def __init__(self, connect, |
61 | 65 |
listen=DEFAULT_LISTEN_TIMEOUT, |
62 | 66 |
error=DEFAULT_ERROR_TIMEOUT, |
63 |
ready=DEFAULT_READY_TIMEOUT): |
|
67 |
ready=DEFAULT_READY_TIMEOUT, |
|
68 |
progress=DEFAULT_PROGRESS_INTERVAL): |
|
64 | 69 |
"""Initializes this class. |
65 | 70 |
|
66 | 71 |
@type connect: number |
... | ... | |
71 | 76 |
@param error: Length of time until errors cause hard failure |
72 | 77 |
@type ready: number |
73 | 78 |
@param ready: Timeout for daemon to become ready |
79 |
@type progress: number |
|
80 |
@param progress: Progress update interval |
|
74 | 81 |
|
75 | 82 |
""" |
76 | 83 |
self.error = error |
77 | 84 |
self.ready = ready |
78 | 85 |
self.listen = listen |
79 | 86 |
self.connect = connect |
87 |
self.progress = progress |
|
80 | 88 |
|
81 | 89 |
|
82 | 90 |
class ImportExportCbBase(object): |
... | ... | |
101 | 109 |
|
102 | 110 |
""" |
103 | 111 |
|
112 |
def ReportProgress(self, ie, private): |
|
113 |
"""Called when new progress information should be reported. |
|
114 |
|
|
115 |
@type ie: Subclass of L{_DiskImportExportBase} |
|
116 |
@param ie: Import/export object |
|
117 |
@param private: Private data passed to import/export object |
|
118 |
|
|
119 |
""" |
|
120 |
|
|
104 | 121 |
def ReportFinished(self, ie, private): |
105 | 122 |
"""Called when a transfer has finished. |
106 | 123 |
|
... | ... | |
157 | 174 |
self._ts_connected = None |
158 | 175 |
self._ts_finished = None |
159 | 176 |
self._ts_cleanup = None |
177 |
self._ts_last_progress = None |
|
160 | 178 |
self._ts_last_error = None |
161 | 179 |
|
162 | 180 |
# Transfer status |
... | ... | |
178 | 196 |
return None |
179 | 197 |
|
180 | 198 |
@property |
199 |
def progress(self): |
|
200 |
"""Returns transfer progress information. |
|
201 |
|
|
202 |
""" |
|
203 |
if not self._daemon: |
|
204 |
return None |
|
205 |
|
|
206 |
return (self._daemon.progress_mbytes, |
|
207 |
self._daemon.progress_throughput, |
|
208 |
self._daemon.progress_percent, |
|
209 |
self._daemon.progress_eta) |
|
210 |
|
|
211 |
@property |
|
181 | 212 |
def active(self): |
182 | 213 |
"""Determines whether this transport is still active. |
183 | 214 |
|
... | ... | |
345 | 376 |
|
346 | 377 |
return False |
347 | 378 |
|
379 |
def _CheckProgress(self): |
|
380 |
"""Checks whether a progress update should be reported. |
|
381 |
|
|
382 |
""" |
|
383 |
if ((self._ts_last_progress is None or |
|
384 |
_TimeoutExpired(self._ts_last_progress, self._timeouts.progress)) and |
|
385 |
self._daemon and |
|
386 |
self._daemon.progress_mbytes is not None and |
|
387 |
self._daemon.progress_throughput is not None): |
|
388 |
self._cbs.ReportProgress(self, self._private) |
|
389 |
self._ts_last_progress = time.time() |
|
390 |
|
|
348 | 391 |
def CheckFinished(self): |
349 | 392 |
"""Checks whether the daemon exited. |
350 | 393 |
|
... | ... | |
358 | 401 |
return True |
359 | 402 |
|
360 | 403 |
if self._daemon.exit_status is None: |
404 |
# TODO: Adjust delay for ETA expiring soon |
|
405 |
self._CheckProgress() |
|
361 | 406 |
return False |
362 | 407 |
|
363 | 408 |
self._ts_finished = time.time() |
... | ... | |
404 | 449 |
"""Finalizes this import/export. |
405 | 450 |
|
406 | 451 |
""" |
407 |
assert error or self.success is not None |
|
408 |
|
|
409 | 452 |
if self._daemon_name: |
410 | 453 |
logging.info("Finalizing %s %r on %s", |
411 | 454 |
self.MODE_TEXT, self._daemon_name, self.node_name) |
... | ... | |
576 | 619 |
return self._ts_begin |
577 | 620 |
|
578 | 621 |
|
622 |
def FormatProgress(progress): |
|
623 |
"""Formats progress information for user consumption |
|
624 |
|
|
625 |
""" |
|
626 |
(mbytes, throughput, percent, _) = progress |
|
627 |
|
|
628 |
parts = [ |
|
629 |
utils.FormatUnit(mbytes, "h"), |
|
630 |
|
|
631 |
# Not using FormatUnit as it doesn't support kilobytes |
|
632 |
"%0.1f MiB/s" % throughput, |
|
633 |
] |
|
634 |
|
|
635 |
if percent is not None: |
|
636 |
parts.append("%d%%" % percent) |
|
637 |
|
|
638 |
# TODO: Format ETA |
|
639 |
|
|
640 |
return utils.CommaJoin(parts) |
|
641 |
|
|
642 |
|
|
579 | 643 |
class ImportExportLoop: |
580 | 644 |
MIN_DELAY = 1.0 |
581 | 645 |
MAX_DELAY = 20.0 |
... | ... | |
772 | 836 |
self.feedback_fn("%s is sending data on %s" % |
773 | 837 |
(dtp.data.name, ie.node_name)) |
774 | 838 |
|
839 |
def ReportProgress(self, ie, dtp): |
|
840 |
"""Called when new progress information should be reported. |
|
841 |
|
|
842 |
""" |
|
843 |
progress = ie.progress |
|
844 |
if not progress: |
|
845 |
return |
|
846 |
|
|
847 |
self.feedback_fn("%s sent %s" % (dtp.data.name, FormatProgress(progress))) |
|
848 |
|
|
775 | 849 |
def ReportFinished(self, ie, dtp): |
776 | 850 |
"""Called when a transfer has finished. |
777 | 851 |
|
... | ... | |
993 | 1067 |
|
994 | 1068 |
self._feedback_fn("Disk %s is now sending data" % idx) |
995 | 1069 |
|
1070 |
def ReportProgress(self, ie, private): |
|
1071 |
"""Called when new progress information should be reported. |
|
1072 |
|
|
1073 |
""" |
|
1074 |
(idx, _) = private |
|
1075 |
|
|
1076 |
progress = ie.progress |
|
1077 |
if not progress: |
|
1078 |
return |
|
1079 |
|
|
1080 |
self._feedback_fn("Disk %s sent %s" % (idx, FormatProgress(progress))) |
|
1081 |
|
|
996 | 1082 |
def ReportFinished(self, ie, private): |
997 | 1083 |
"""Called when a transfer has finished. |
998 | 1084 |
|
Also available in: Unified diff