Example #1
0
    def on_version_hook_event(self, event):
        status = event.cargo[HOOK_STATUS]

        if status == HOOK_STATUS_COMPLETED:
            version = event.cargo[HOOK_MESSAGE]
            if self.job.version == version:
                if settings.hooks.ready:
                    logger.debug("Start ready hook")
                    # Start ready check
                    self.stop_ready_hook = run_hook(
                        settings.hooks.ready,
                        self.root_machine.inbox,
                        args=[self.job.meta],
                    )
                else:
                    logger.info("Skip ready hook")
                    self.job_succeeded(
                        JobSuccessStatus.COMPLETE_NO_READY_CHECK.value)
                    self.publish(pysm.Event(JOB_INSTALLATION_COMPLETE))
            else:
                message = f"Expected version '{self.job.version}', got '{version}'"
                logger.warning(message)
                self.job_failed(JobFailedStatus.VERSION_MISMATCH.value,
                                message=message)
                self.publish(pysm.Event(JOB_INSTALLATION_COMPLETE))
        elif status in (HOOK_STATUS_FAILED, HOOK_STATUS_TIMED_OUT):
            error_message = event.cargo[HOOK_MESSAGE]
            logger.error(f"Version hook failed: {error_message}")
            self.job_failed(JobFailedStatus.VERSION_HOOK_FAILED.value,
                            message=error_message)
            self.publish(pysm.Event(JOB_INSTALLATION_COMPLETE))
Example #2
0
    def on_enter(self, state, event):
        if self.job.status == JobStatus.QUEUED.value:
            version_hook = settings.hooks.version
            force = self.job.force

            if force or not version_hook:
                logger.info(
                    f"Skip version check [force={force}, {version_hook if version_hook else 'no-hook'}]"  # noqa
                )
                return self._job_verified()

            logger.debug("Start version check")
            self.stop_version_hook = run_hook(version_hook,
                                              self.root_machine.inbox,
                                              args=[self.job.meta])

        elif self.job.status == JobStatus.IN_PROGRESS.value:
            # If the restart is initiated the installation is done
            if self.job.internal_state == JobProgressStatus.REBOOT_START.value:
                logger.info("Installation done")
                self.publish(
                    pysm.Event(JOB_INSTALLATION_DONE, **{JOB: self.job}))
            # Redo the whole update process
            else:
                logger.info("Redo job process")
                return self._job_verified()
        else:
            raise Exception(f"Unexpected job status: {self.job.status}")
Example #3
0
def test_stop_event(mocker):
    mock = mocker.patch("upparat.hooks._hook")
    stop_event = run_hook("dummy", None, join=True)
    stop_event.set()

    _, kwargs = mock.call_args
    assert kwargs["stop_event"].is_set()
Example #4
0
def test_subprocess_args(mocker):
    mock = _subprocess_mock(mocker, [0], [])
    default_timer = mocker.Mock(side_effect=[0, 10])
    mocker.patch("upparat.hooks.default_timer", default_timer)

    elapsed = 10  # 10 - 0
    command = "noop"
    retry_count = 0

    run_hook(command, mocker.MagicMock(), args=None, join=True)

    mock.assert_called_once_with(
        [command, str(elapsed), str(retry_count)],
        bufsize=1,
        stdout=subprocess.PIPE,
        universal_newlines=True,
    )
Example #5
0
def test_fail(mocker):
    command = "fail"
    exit_code = 33

    mock = _subprocess_mock(mocker, [exit_code], [])

    queue = mocker.MagicMock()

    run_hook(command, queue, join=True)

    assert mock.call_count == 1

    args, _ = queue.put.call_args

    event = args[0]
    assert event.name == HOOK
    assert event.cargo[HOOK_STATUS] == HOOK_STATUS_FAILED
    assert event.cargo[HOOK_MESSAGE] == f"Exit code: {exit_code}"
Example #6
0
 def on_enter(self, state, event):
     if not settings.hooks.version:
         logger.info("Skip version check")
         self.job_succeeded(
             JobSuccessStatus.COMPLETE_NO_VERSION_CHECK.value)
         self.publish(pysm.Event(JOB_INSTALLATION_COMPLETE))
     else:
         # Start version check
         logger.debug("Start version check")
         self.stop_version_hook = run_hook(settings.hooks.version,
                                           self.root_machine.inbox,
                                           args=[self.job.meta])
Example #7
0
def test_retry(mocker):
    command = "noop"
    retry_count = 2
    return_value = "0.1.1"

    mock = _subprocess_mock(mocker, [RETRY_EXIT_CODE, 0], [return_value])

    queue = mocker.MagicMock()

    settings.hooks.retry_interval = 0

    run_hook(command, queue, join=True)

    assert mock.call_count == retry_count

    args, _ = queue.put.call_args

    event = args[0]
    assert event.name == HOOK
    assert event.cargo[HOOK_STATUS] == HOOK_STATUS_COMPLETED
    assert event.cargo[HOOK_MESSAGE] == return_value
Example #8
0
def test_retry_timeout(mocker):
    command = "long"

    mock = _subprocess_mock(mocker, [RETRY_EXIT_CODE, RETRY_EXIT_CODE], [])

    queue = mocker.MagicMock()

    settings.hooks.retry_interval = 0
    settings.hooks.max_retries = 1

    run_hook(command, queue, join=True)

    assert mock.call_count == settings.hooks.max_retries

    args, _ = queue.put.call_args

    event = args[0]
    assert event.name == HOOK
    assert event.cargo[HOOK_STATUS] == HOOK_STATUS_TIMED_OUT
    assert (event.cargo[HOOK_MESSAGE] ==
            f"Timeout after {settings.hooks.retry_interval}s")
Example #9
0
    def on_enter(self, state, event):
        hook = settings.hooks.download
        force = self.job.force

        if hook and not force:
            self.stop_download_hook = run_hook(
                hook, self.root_machine.inbox, args=[self.job.meta]
            )
        else:
            logger.info(
                f"Skip download hook: Hook={hook if hook else 'no-hook'}, force={force}."
            )
            self.start_download_thread()
Example #10
0
 def on_enter(self, state, event):
     if settings.hooks.restart:
         logger.info("Initiate restart")
         self.job_progress(JobProgressStatus.REBOOT_START.value)
         self.stop_restart_hook = run_hook(
             settings.hooks.restart,
             self.root_machine.inbox,
             args=[self.job.meta, self.job.force],
         )
     else:
         logger.info("No restart hook provided")
         self.job_succeeded(JobSuccessStatus.NO_RESTART_HOOK_PROVIDED.value)
         self.publish(pysm.Event(RESTART_INTERRUPTED))
Example #11
0
 def on_enter(self, state, event):
     # Start install hook
     if settings.hooks.install:
         logger.info("Start installation")
         self.job_progress(JobProgressStatus.INSTALLATION_START.value)
         self.stop_install_hook = run_hook(
             settings.hooks.install,
             self.root_machine.inbox,
             args=[self.job.meta, self.job.filepath],
         )
     else:
         logger.info("No installation hook provided")
         # mark as succeeded because maybe there is no "install" step
         # necessary since we only want to distribute a file
         self.job_succeeded(
             JobSuccessStatus.NO_INSTALLATION_HOOK_PROVIDED.value)
         self.publish(pysm.Event(INSTALLATION_INTERRUPTED))