76 def ok(self): |
86 def ok(self): |
77 return self.errors.ok() |
87 return self.errors.ok() |
78 |
88 |
79 def add_error(self, error): |
89 def add_error(self, error): |
80 self.errors=self.errors.combine(error) |
90 self.errors=self.errors.combine(error) |
|
91 |
|
92 def name(self): |
|
93 if 'reason' in self.detail: |
|
94 return str(self.type) + '.' + self.detail['reason'] |
|
95 else: |
|
96 return str(self.type) |
81 |
97 |
82 |
98 |
83 class Status(Operation): |
99 class Status(Operation): |
84 def __init__(self, backup, op=None): |
100 def __init__(self, backup, op=None): |
85 op=None |
101 op=None |
445 self.borg_instance=inst |
461 self.borg_instance=inst |
446 self.current_operation=op |
462 self.current_operation=op |
447 # Update scheduled time to real starting time to schedule |
463 # Update scheduled time to real starting time to schedule |
448 # next run relative to this |
464 # next run relative to this |
449 self.current_operation.start_time=MonotonicTime.now() |
465 self.current_operation.start_time=MonotonicTime.now() |
450 self.state=State.ACTIVE |
|
451 # Reset error status when starting a new operation |
466 # Reset error status when starting a new operation |
452 self.__update_status() |
467 self.__update_status(State.ACTIVE) |
453 |
468 |
454 t_log.start() |
469 t_log.start() |
455 t_res.start() |
470 t_res.start() |
456 |
471 |
457 |
472 |
575 def __main_thread_wait_schedule(self): |
590 def __main_thread_wait_schedule(self): |
576 op=None |
591 op=None |
577 if self._pause: |
592 if self._pause: |
578 self.logger.info("Waiting for resume to be signalled") |
593 self.logger.info("Waiting for resume to be signalled") |
579 |
594 |
580 self.state=State.PAUSED |
595 self.__update_status(State.PAUSED) |
581 self.__update_status() |
|
582 |
596 |
583 self._cond.wait() |
597 self._cond.wait() |
584 else: |
598 else: |
585 if not self.scheduled_operation: |
599 if not self.scheduled_operation: |
586 op=self.__next_operation_unlocked() |
600 op=self.__next_operation_unlocked() |
587 if op: |
601 if op: |
588 self.logger.info("Scheduling '%s' (detail: %s) on %s [%s]" % |
|
589 (str(op.type), op.detail or 'none', |
|
590 op.start_time.isoformat(), |
|
591 op.start_time.__class__.__name__)) |
|
592 |
|
593 self.scheduled_operation=op |
602 self.scheduled_operation=op |
594 self.state=State.SCHEDULED |
603 |
595 self.__update_status() |
604 self.__update_status(State.SCHEDULED) |
596 |
605 |
597 # Wait under scheduled wait |
606 # Wait under scheduled wait |
598 self.scheduler.wait_until(op.start_time, self._cond, self.backup_name) |
607 eventname=op.name() + '@' + self.backup_name |
|
608 self.scheduler.wait_until(op.start_time, self._cond, eventname) |
599 else: |
609 else: |
600 # Nothing scheduled - just wait |
610 # Nothing scheduled - just wait |
601 self.logger.info("Waiting for manual scheduling") |
611 self.logger.info("Waiting for manual scheduling") |
602 |
612 |
603 self.state=State.INACTIVE |
613 self.__update_status(State.INACTIVE) |
604 self.__update_status() |
|
605 |
614 |
606 self._cond.wait() |
615 self._cond.wait() |
607 |
616 |
608 # Main thread/3. If there is a scheduled operation (it might have been |
617 # Main thread/3. If there is a scheduled operation (it might have been |
609 # changed manually from 'op' created in __main_thread_wait_schedule above), |
618 # changed manually from 'op' created in __main_thread_wait_schedule above), |
610 # queue it on the repository, and launch the operation once repository |
619 # queue it on the repository, and launch the operation once repository |
611 # available |
620 # available |
612 def __main_thread_queue_and_launch(self): |
621 def __main_thread_queue_and_launch(self): |
613 if self.scheduled_operation: |
622 if self.scheduled_operation: |
614 self.logger.debug("Queuing") |
623 |
615 self.state=State.QUEUED |
624 self.__update_status(State.QUEUED) |
616 self.__update_status() |
625 |
617 res=self.repository.queue_action(self._cond, |
626 res=self.repository.queue_action(self._cond, |
618 action=self.__launch_and_wait, |
627 action=self.__launch_and_wait, |
619 name=self.backup_name) |
628 name=self.backup_name) |
620 if not res: |
629 if not res: |
621 self.logger.debug("Queueing aborted") |
630 self.logger.debug("Queueing aborted") |
709 callback=self.__status_update_callback |
718 callback=self.__status_update_callback |
710 status=Status(self) |
719 status=Status(self) |
711 |
720 |
712 return status, callback |
721 return status, callback |
713 |
722 |
714 def __update_status(self): |
723 def __update_status(self, state): |
|
724 self.logger.debug("Entering %s state", str(state)) |
|
725 self.state=state |
715 status, callback = self.__status_unlocked() |
726 status, callback = self.__status_unlocked() |
716 if callback: |
727 if callback: |
717 #self._cond.release() |
728 #self._cond.release() |
718 try: |
729 try: |
719 callback(status) |
730 callback(status) |