Example #1
0
    def restart(self, **kwargs):
        """
        :param kwargs: passed from zoom.handlers.control_agent_handlers
        """
        # if not self._action_is_ready('restart', allow_undefined=True):
        #     self._log.info('Restart action not ready.')
        #     return

        self._log.info('Running Restart. Queuing stop, unregister, start.')
        self._action_queue.clear()
        self._action_queue.append_unique(Task('stop', kwargs=kwargs))
        self._action_queue.append_unique(Task('unregister'))
        self._action_queue.append_unique(Task('start', kwargs=kwargs))
        return 0
    def on_exist(self, event=None):
        try:
            if self.zkclient.exists(self._path, watch=self.on_exist):
                data, stat = self.zkclient.get(self._path)
                task = Task.from_json(data)
                self._log.info('Found work to do: {0}'.format(task))
                if task.result == ApplicationState.OK:
                    self._log.debug('Task is already complete: {0}'.format(task))
                    return  # ignore tasks that are already done

                if task.name in SENTINEL_METHODS:
                    if task.target is not None:
                        self.send_work_single(task)
                    else:
                        self.send_work_all(task)
                    self._log.info("Submitted task {0} for {1}"
                                   .format(task.name, task.target))
                else:
                    err = 'Invalid work submitted: {0}'.format(task.name)
                    self._log.warning(err)

                task.result = ApplicationState.OK
                self._log.info(task.to_json())
                self.zkclient.set(self._path, task.to_json())

        except NoNodeError:
            self._log.debug('No Node at {0}'.format(self._path))
Example #3
0
 def clear_task_queue(self):
     self._log.info('Starting, so clearing task queue.')
     if self.zkclient.exists(self._path):
         data, stat = self.zkclient.get(self._path)
         task = Task.from_json(data)
         task.result = CommandType.CANCEL
         self.zkclient.set(self._path, task.to_json())
Example #4
0
 def clear_task_queue(self):
     self._log.info('Starting, so clearing task queue.')
     if self.zkclient.exists(self._path):
         data, stat = self.zkclient.get(self._path)
         task = Task.from_json(data)
         task.result = CommandType.CANCEL
         self.zkclient.set(self._path, task.to_json())
Example #5
0
    def on_exist(self, event=None):
        try:
            if self.zkclient.exists(self._path, watch=self.on_exist):
                data, stat = self.zkclient.get(self._path)
                task = Task.from_json(data)
                self._log.info('Found work to do: {0}'.format(task))
                if task.result == ApplicationState.OK:
                    self._log.debug(
                        'Task is already complete: {0}'.format(task))
                    return  # ignore tasks that are already done

                if task.name in SENTINEL_METHODS:
                    if task.target is not None:
                        self.send_work_single(task)
                    else:
                        self.send_work_all(task)
                    self._log.info("Submitted task {0} for {1}".format(
                        task.name, task.target))
                else:
                    err = 'Invalid work submitted: {0}'.format(task.name)
                    self._log.warning(err)

                task.result = ApplicationState.OK
                self._log.info(task.to_json())
                self.zkclient.set(self._path, task.to_json())

        except NoNodeError:
            self._log.debug('No Node at {0}'.format(self._path))
Example #6
0
    def _callback(self):
        self._log.info('Callback triggered for {0}:\n{1}'.format(
            self, self._predicate))

        if self.disabled:
            self._log.info('Not running action {0}. It is disabled.'.format(
                self.name))
            return
        # ensure all predicates are started
        elif not self.started:
            self._log.warning('All predicates are not started. '
                              'Ignoring action {0}'.format(self.name))
            return
        # ensure all predicates are met
        elif not self._predicate.met:
            self._log.debug('Not triggering action for {0}. '
                            'Predicate not met.'.format(self))

            # check if there are operational dependencies involved.
            # If so, run the operational action. This defaults to 'stop'.
            if self._predicate.operationally_relevant and \
                    self._op_action is not None and \
                    self._mode != ApplicationMode.MANUAL:
                self._log.info('Operational relevancy detected. '
                               'Triggering operation action.')
                self._action_queue.append_unique(Task(self._op_action.__name__,
                                                      func=self._op_action),
                                                 sender=str(self))
            else:
                self._log.debug('Operation dep={0}, Mode={1}'.format(
                    self._predicate.operationally_relevant, self._mode))
            return

        elif self._action is not None:
            self._log.debug('There is a callback and all predicates are met.')
            if (self._mode != ApplicationMode.MANUAL
                    or not self._mode_controlled):
                self._action_queue.append_unique(Task(self.name,
                                                      func=self._execute,
                                                      kwargs=self.kwargs),
                                                 sender=str(self))
            else:
                self._log.info(
                    'Run mode is set to Manual. Not triggering "{0}"'
                    ' action based on dependency change.'.format(self.name))
        else:
            self._log.info('Nothing was done with callback')
Example #7
0
 def start_if_ready(self, **kwargs):
     start_action = self._actions.get('start', None)
     if start_action is not None and start_action.ready:
         start_action.run(**kwargs)
     # if start action doesn't exist, a.k.a. read only
     elif start_action is None:
         self.start(**kwargs)
     else:
         self._action_queue.append(Task('react', kwargs=kwargs))
     return 0
Example #8
0
 def stop(self):
     """
     Stops the Process/Thread
     """
     try:
         self._log.info('Terminating {0} child process'.format(self.name))
         self.cancel_current_task()
         self.add_work(Task('terminate', block=True), immediate=True)
     except Exception as e:
         self._log.warning(
             'Exception with stopping {0} child process: {1}'.format(
                 self.name, e))
Example #9
0
 def post(self, target=None):
     """
     @api {post} /api/v1/status[/:target] Log out and retrieve status of components (plaintext)
     @apiDescription This will retrieve the status of all the Sentinel objections
     (Components, Actions, Predicates). The POST is best used from curl.
     @apiVersion 1.0.0
     @apiName CurlGetStatus
     @apiGroup Sentinel Agent
     """
     tc = self.application.task_client
     task = Task('status', target=target, block=True, retval=True)
     if target is not None:
         result = tc.send_work_single(task, wait=True, immediate=True)
         self.write(result.get('result'))
     else:
         result = tc.send_work_all(task, wait=True, immediate=True)
         for i in result.values():
             self.write(i.get('result'))
Example #10
0
    def get(self, target=None):
        """
        @api {get} /api/v1/status[/:target] Log out and retrieve status of components (html)
        @apiDescription This will retrieve the status of all the Sentinel objections
        (Components, Actions, Predicates). The GET is best used from a browser.
        @apiVersion 1.0.0
        @apiName WebGetStatus
        @apiGroup Sentinel Agent
        """
        tc = self.application.task_client
        task = Task('status', target=target, block=True, retval=True)
        if target is not None:
            tc.send_work_single(task, wait=True, immediate=True)
        else:
            tc.send_work_all(task, wait=True, immediate=True)

        line_count = 50 * len(self.application.children.keys())
        self.render('../templates/log.html', data=get_log(count=line_count))
Example #11
0
    def post(self, work=None, target=None):
        """
        @api {post} /api/v1/:work[/:target] Submit a task to Sentinel
        @apiDescription You can use this to mimic the tasks sent from Zoom.
        For example: /api/v1/stop/foo will stop the application foo.
        @apiVersion 1.0.0
        @apiName SubmitTask
        @apiGroup Sentinel Agent
        """
        tc = self.application.task_client
        task = Task(work, target=target, block=True, retval=True)

        if target is not None:
            result = tc.send_work_single(task, immediate=True)
            self.write(json.dumps(result))
        else:
            result = tc.send_work_all(task, immediate=True)

        self.write(json.dumps(result))
Example #12
0
    def _on_update(self, event):
        """
        Callback for the data watch on the task node
        :type event: kazoo.protocol.states.WatchedEvent
        """
        try:
            data, stat = self._zoo_keeper.get(event.path)
            task = Task.from_json(data)
            if task.result is not None:
                self._remove(task, event.path)
                self._submit_next(task.host)

            else:
                logging.info('Task result is {0}. Resetting watch'
                             .format(task.result))
                self._zoo_keeper.get(event.path, watch=self._on_update)

        except NoNodeError:
            pass
Example #13
0
    def _on_update(self, event):
        """
        Callback for the data watch on the task node
        :type event: kazoo.protocol.states.WatchedEvent
        """
        try:
            data, stat = self._zoo_keeper.get(event.path)
            task = Task.from_json(data)
            if task.result is None:
                logging.info('Task result is {0}. Resetting watch'.format(
                    task.result))
                self._zoo_keeper.get(event.path, watch=self._on_update)
            elif task.result == CommandType.CANCEL:
                logging.info('Sentinel {0} requested task clear.'.format(
                    task.host))
                self._remove(task, event.path, clear_queue=True)
            else:
                self._remove(task, event.path)
                self._submit_next(task.host)

        except NoNodeError:
            pass
    def post(self):
        """
        @api {post} /api/v1/agent/ Create Task from json and add to TaskServer
        @apiParam {Boolean} [stay_down=null] Used to signal to Sentinel that the application was brought down on purpose
        @apiParam {String} [login_user=null] The user that submitted the task
        @apiParam {String} command The function Sentinel should run
        @apiParam {String} componentId The app targeted for the task
        @apiParam {String} applicationHost The host the app is running on
        @apiVersion 1.0.0
        @apiName CreateTask
        @apiGroup Task
        """
        try:
            user = self.get_argument("user", default=None)
            command = self.get_argument("command")
            app = self.get_argument("componentId")

            kwarguments = {
                'stay_down': self.get_argument("stay_down", default=None),
                'login_user': user,
            }
            task = Task(command,
                        target=app,
                        kwargs=kwarguments,
                        host=self.get_argument("applicationHost"),
                        submitted=datetime.datetime.now().strftime('%Y%m%d %H:%M:%S'))

            logging.info("Received task request from client {0}: {1}"
                         .format(self.request.remote_ip, task))

            cancel = task.name == CommandType.CANCEL
            self.task_server.add_task(task, is_cancel=cancel)
            self._send_to_chat_server(user, app, command)

        except Exception as e:
            self.set_status(INTERNAL_SERVER_ERROR)
            self.write(json.dumps({'errorText': str(e)}))
            logging.exception(e)
Example #15
0
 def dep_restart(self, **kwargs):
     self._run_check_mode = True  # only used in self.start()
     self._action_queue.append(Task('start_if_ready', kwargs=kwargs))
     return 0