Пример #1
0
def create_periodic_task(name,
                         task,
                         expires=None,
                         args=None,
                         kwargs=None,
                         frequency=None,
                         crontab_minute=None,
                         crontab_hour=None,
                         crontab_day_of_week=None,
                         crontab_day_of_month=None,
                         crontab_month_of_year=None):
    """

    :return:
    """
    task_data = {
        'name': name,
        'task': task,
        'expires': expires,
    }
    if frequency is not None:
        task_data['interval'] = {'every': frequency, 'period': 'minutes'}
    crontab = {}
    if crontab_minute is not None:
        crontab['minute'] = crontab_minute
    if crontab_hour is not None:
        crontab['hour'] = crontab_hour
    if crontab_day_of_week is not None:
        crontab['day_of_week'] = crontab_day_of_week
    if crontab_day_of_month is not None:
        crontab['day_of_month'] = crontab_day_of_month
    if crontab_month_of_year is not None:
        crontab['month_of_year'] = crontab_month_of_year

    if len(crontab) != 0:
        task_data['crontab'] = crontab

    if args is not None:
        if isinstance(args, list):
            task_data['args'] = json.dumps(args)
        else:
            raise natrix_exception.ClassInsideException(
                message=u'periodic task args is not list')

    if kwargs is not None:
        if isinstance(kwargs, dict):
            task_data['kwargs'] = json.dumps(kwargs)
        else:
            raise natrix_exception.ClassInsideException(
                message=u'periodic task kwargs is not dict')

    serializer = PeriodicTaskSerializer(data=task_data)
    if serializer.is_valid():
        serializer.save()
    else:
        raise natrix_exception.ClassInsideException(message=serializer.errors)
Пример #2
0
    def store(self):
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        if not hasattr(self, 'is_store'):
            raise natrix_exceptions.ClassInsideException(
                message=
                'Must call _get_message to generate message before store.')

        if self.is_store:
            logger.info('A message(response) can only store one time')

        res = store_message(type=self._message_type, data=self.message)
        logger.debug('store result : {}'.format(res))
Пример #3
0
    def _get_message(self):
        """

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        if not hasattr(self, 'is_store'):
            self.is_store = False

        message = {'errorcode': 1408, 'errorinfo': u'Terminal do not consume'}
        message['command_uuid'] = self._validated_data['uuid']
        message['command_generate_time'] = int(
            self._validated_data['generate_timestamp'] * 1000)
        message['terminal'] = self._validated_data['terminal']

        terminal_api = TerminalAPI(message['terminal'])

        message['organization_id'] = terminal_api.get_org_ids()
        message['organization_name'] = terminal_api.get_org_names()
        message['organization_isp'] = terminal_api.get_register_isp()

        message['province'] = terminal_api.get_register_province()
        message['city'] = terminal_api.get_register_city()

        message['command_response_process_time'] = int(time.time() * 1000)

        self.message = message
    def summary_presentation(self, instance=None):
        """Summary info about organization

        :param instance: an instance of organization
        :return:
        """

        org_instance = None
        if not (instance is None):
            org_instance = instance
        elif hasattr(self, 'instance'):
            org_instance = self.instance

        if not isinstance(org_instance, Organization):
            raise natrix_exception.ParameterInvalidException(
                parameter='instance')

        try:
            ret = OrderedDict()
            ret['id'] = org_instance.id
            ret['name'] = org_instance.name
            ret['full_name'] = org_instance.get_full_name()
            ret['addresses'] = map(lambda addr: str(addr),
                                   org_instance.get_addresses())
            ret['networks'] = map(lambda n: str(n),
                                  org_instance.get_networks())
            return ret

        except Exception as e:
            logger.error(e)
            raise natrix_exception.ClassInsideException(
                message='summary Organization error')
Пример #5
0
    def _update_command_status(self):
        """更新command状态

        :return:
        """

        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        terminal_tag = self._validated_data['terminal']
        command_uuid = str(self._validated_data['uuid'])
        timestamp = self._validated_data['generate_timestamp']

        command_exist, record_exist = AdapterCommandStatus.remove_command_cache(
            command_uuid, timestamp, terminal_tag)

        if not command_exist:
            logger.error(
                'There is not command instance for this dead message: {command_uuid}-{timestamp}'
                .format(command_uuid=command_uuid, timestamp=timestamp))
            return command_exist

        if not record_exist:
            logger.error(
                'There is not command record for this dead message: {command_uuid}-{timestamp}-{terminal}'
                .format(command_uuid=command_uuid,
                        timestamp=timestamp,
                        terminal=terminal_tag))
            return record_exist

        return True
Пример #6
0
    def _update_command_status(self):
        """Update command status in cache.

        Note: be same with CommandTerminal._update_command_status

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')
        command = self._validated_data['command']
        command_uuid = str(command.get('uuid'))
        terminal_tag = command.get('terminal')
        timestamp = self._get_command_stamp()

        command_exist, record_exist = AdapterCommandStatus.remove_command_cache(
            command_uuid, timestamp, terminal_tag)

        if not command_exist:
            logger.error(
                'There is not command instance for this response message: {command_uuid}-{timestamp}'
                .format(command_uuid=command_uuid, timestamp=timestamp))
            return command_exist

        if not record_exist:
            logger.error(
                'There is not command record for this dead message: {command_uuid}-{timestamp}-{terminal}'
                .format(command_uuid=command_uuid,
                        timestamp=timestamp,
                        terminal=terminal_tag))
            return record_exist

        return True
Пример #7
0
    def get(self, request, format=None):
        feedback = {'permission': True}
        try:
            id = request.GET.get('id')
            try:
                org_instance = Organization.objects.get(id=id)
                serializer = organization_serializer.OrganizationSerializer(
                    instance=org_instance)
                feedback['data'] = {
                    'code': 200,
                    'message': u'Terminal device summary info!',
                    'info': serializer.summary_presentation()
                }
            except Organization.DoesNotExist:
                feedback['data'] = ErrorCode.parameter_invalid(
                    'id', reason=u'Organization record is not exist!')
                raise natrix_exception.ParameterInvalidException(
                    parameter='id')
            except natrix_exception.BaseException as e:
                feedback['data'] = ErrorCode.sp_code_bug(e.get_log())
                raise natrix_exception.ClassInsideException(
                    message=e.get_log())
        except natrix_exception.BaseException as e:
            logger.info(e.get_log())

        return JsonResponse(data=feedback)
Пример #8
0
    def init_request_queue(channel, tag):
        """初始化请求队列相关的信息

        :param channel:
        :return:
        """
        try:
            exchange_name = EXCHANGE_REQUEST_TEMPLATE.format(tag=tag)

            channel.exchange_declare(exchange=exchange_name,
                                     exchange_type='direct')
            channel.queue_declare(queue=exchange_name,
                                  durable=True,
                                  arguments={
                                      'x-message-ttl': 120000,
                                      'x-dead-letter-exchange':
                                      EXCHANGE_COMMAND_DEAD,
                                      'x-dead-letter-routing-key':
                                      'dead_command'
                                  })
            channel.queue_bind(exchange=exchange_name,
                               queue=exchange_name,
                               routing_key='command')

        except Exception as e:
            logger.error(e)
            raise natrix_exceptions.ClassInsideException(message=str(e))
Пример #9
0
    def get(self, request):
        feedback = {
            'permission': True
        }
        try:
            sn = request.GET.get('sn')
            if sn is None:
                feedback['data'] = ErrorCode.parameter_missing('sn')
                raise natrix_exception.ParameterMissingException(parameter='sn')
            try:
                device = TerminalDevice.objects.get(sn=sn)
                logger.debug('device info {}'.format(device))
            except TerminalDevice.DoesNotExist:
                feedback['data'] = ErrorCode.parameter_invalid(
                    parameter='sn', reason=u'The record is not exist')
                raise natrix_exception.ParameterInvalidException(parameter='sn')

            try:
                serializer = alive_serializer.AdavnceHardwareSerializer(instance=device)
                feedback['data'] = {
                    'code': 200,
                    'message': u'终端设备硬件信息',
                    'info': serializer.data
                }
                return JsonResponse(data=feedback)
            except natrix_exception.BaseException as e:
                feedback['data'] = ErrorCode.sp_db_fault(aspect=u'Terminal Hardware serializer error')
                raise natrix_exception.ClassInsideException(message=u'Terminal Hardware serializer error')

        except natrix_exception.BaseException as e:
            logger.info(e.get_log())

        return JsonResponse(data=feedback)
Пример #10
0
    def distribute_command(self):
        """命令分发

        将command分发到不同的RabbitMQ队列中。

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        with mqservice.MQService.get_purge_channel() as channel:
            try:
                terminals = [
                    t.get('mac') for t in self._validated_data['terminals']
                ]
                command_timestamp = self._validated_data['timestamp']
                command = self._validated_data['command']

                publish_data = {
                    'uuid': str(command.get('command_uuid')),
                    'protocol': command.get('command_protocol'),
                    'destination': command.get('command_destination'),
                    'parameters': command.get('command_parameters'),
                    'generate_timestamp': command_timestamp,
                }

                # TODO: 思考如果取消重复声明、绑定(队列)
                for terminal_tag in terminals:

                    AdapterMQSetting.init_request_queue(channel, terminal_tag)
                    exchange_name = EXCHANGE_REQUEST_TEMPLATE.format(
                        tag=terminal_tag)

                    publish_data['terminal'] = terminal_tag

                    channel.basic_publish(
                        exchange=exchange_name,
                        routing_key='command',
                        body=json.dumps(publish_data),
                        properties=pika.BasicProperties(delivery_mode=2))
            except Exception as e:
                # TODO: 梳理pika的异常
                logger.error(e)
                raise natrix_exceptions.ClassInsideException(
                    message=u'Distribute command failed!')
Пример #11
0
    def to_representation(self, instance):
        if not isinstance(instance, TerminalDevice):
            raise natrix_exception.ParameterInvalidException(
                parameter='instance')

        try:
            ret = OrderedDict()
            terminals = instance.terminal_set.all()
            total = 0
            active = 0
            alive = 0
            for t in terminals:
                total += 1
                if t.is_valid():
                    active += 1
                if t.is_alive():
                    alive += 1

            ret['sn'] = instance.sn
            ret['hostname'] = instance.hostname
            ret['type'] = instance.product
            ret['os_type'] = instance.os_type
            ret['os_version'] = '[{}]-[{}]'.format(instance.os_major_version,
                                                   instance.os_minor_version)
            ret['client_version'] = instance.natrixclient_version
            ret['status'] = instance.status
            ret['update_time'] = instance.last_online_time
            ret['comment'] = instance.comment
            ret['device_alert'] = instance.device_alert
            ret['terminal_alert'] = instance.terminal_alert
            register = instance.register
            ret['reg_orgs'] = map(
                lambda item: {
                    'id': item.id,
                    'name': item.name,
                    'desc': item.get_full_name()
                },
                register.organizations.all() if register else [])
            ret['detect_orgs'] = map(
                lambda item: {
                    'id': item.id,
                    'name': item.name,
                    'desc': item.get_full_name()
                }, instance.organizations.all())
            segments = map(lambda t: t.get_segment(),
                           instance.terminal_set.all())
            ret['segments'] = [s for s in segments if s]

            ret['terminal_total'] = total
            ret['terminal_active'] = active
            ret['terminal_alive'] = alive

            return ret

        except Exception as e:
            logger.error('Serializer Terminal Device ERROR: {}'.format(e))
            raise natrix_exception.ClassInsideException(
                message=u'{}'.format(e))
Пример #12
0
    def notify(self, message):
        """send message

        :param message:
        :return:
        """
        if not (self.valid_to(self.to) and self.to):
            raise natrix_exceptions.ClassInsideException(
                message=
                u'You must have a valid paremeter(to) before calling `.notify()`'
            )
Пример #13
0
    def _get_command_stamp(self):
        """Get command timestamp ().

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        return self._validated_data['stamp'].get(
            'server_request_generate_time')
Пример #14
0
    def process(self):
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        try:
            # 下发command到终端
            self.distribute_command()
            # 初始化command状态
            self.init_command_status()
        except natrix_exceptions.BaseException as e:
            logger.error('Distribute command failed: {}'.format(e.get_log()))
Пример #15
0
    def store(self, stage='dead'):
        """持久化存储

        :return:
        """

        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        if not hasattr(self, 'is_store'):
            raise natrix_exceptions.ClassInsideException(
                message=
                'Must call _get_message to generate message before store.')

        if self.is_store:
            logger.info('A message(dead) can only store one time')
            return

        res = store_message(type='error', data=self.message)
        logger.info('store result : {}'.format(res))
Пример #16
0
    def is_valid(self, model):
        if not issubclass(model, Model):
            raise natrix_exception.ClassInsideException(message=u'IDSerializer parameter error!')

        flag = super(IDSerializer, self).is_valid()
        if not flag:
            return flag
        try:
            self.instance = model.objects.get(id=self.validated_data.get('id'))
        except model.DoesNotExist:
            self._errors['id'] = u'不能检索到相应数据!'
            flag = False

        return flag
Пример #17
0
    def _response_message_process(self):
        """

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        status_res = self._update_command_status()
        if not status_res:
            logger.error(
                'Update command status errro, drop this response message!')
            return
        self._get_message()
        self.store()
Пример #18
0
    def get_event(self):
        if not hasattr(self, 'curr_alert_state'):
            logger.error('The event only exist after you call keep_alive ({}).'.format(self.pk))
            raise natrix_exception.ClassInsideException(message=u'Call get_event before keep_alive.')

        if self.last_alert_state:
            if self.curr_alert_state:
                return 'aliving', 0
            else:
                # first loss of communication
                return 'dead-first', self.state_info['update_time']
        else:
            if self.curr_alert_state:
                return 'recovery', self.state_info['update_time']
            else:
                return 'dead', self.state_info['timestamp'] - self.state_info['first_alert_time']
Пример #19
0
    def init_command_status(self):
        """初始化command状态

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        terminals = [t.get('mac') for t in self._validated_data['terminals']]
        command_uuid = self._validated_data.get('command').get('command_uuid')
        command_protocol = self._validated_data.get('command').get(
            'command_protocol')
        timestamp = self._validated_data.get('timestamp')
        AdapterCommandStatus.add_command_cache(str(command_uuid), timestamp,
                                               terminals, command_protocol)
Пример #20
0
 def status_change(self, status):
     if status in ('active', 'maintain'):
         terminal_status = status
     elif status in ('posting'):
         terminal_status = 'active'
     else:
         logger.error('Configure terminal deivce status with an error status ({})'.format(status))
         raise natrix_exception.ClassInsideException(
             message='models.TerminalDevice.status_change with an error parameter(status={})'.format(status))
     with transaction.atomic():
         self.status = status
         terminals = self.terminal_set.all()
         for terminal in terminals:
             terminal.status = terminal_status
             terminal.save()
         self.save()
Пример #21
0
    def _get_message(self):
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        if not hasattr(self, 'is_store'):
            self.is_store = False

        command = self._validated_data['command']
        data = self._validated_data['data']
        stamp = self._validated_data['stamp']

        message = dict()
        # command info
        message['command_uuid'] = str(command.get('uuid'))
        message['command_generate_time'] = int(self._get_command_stamp() *
                                               1000)

        # terminal info
        terminal = command.get('terminal')
        message.update(self._get_terminal_info(terminal))

        # timestamp info: from second convert to millisecond
        message['response_process_time'] = int(time.time() * 1000)

        message['terminal_request_receive_time'] = int(
            stamp.get('terminal_request_receive_time') * 1000)
        message['terminal_request_send_time'] = int(
            stamp.get('terminal_request_send_time') * 1000)
        if stamp.get('terminal_response_receive_time'):
            response_receive_time = int(
                stamp.get('terminal_response_receive_time') * 1000)
        else:
            response_receive_time = None
        message['terminal_response_receive_time'] = response_receive_time

        if stamp.get('terminal_response_return_time'):
            response_return_time = int(
                stamp.get('terminal_response_return_time') * 1000)
        else:
            response_return_time = None
        message['terminal_response_return_time'] = response_return_time

        # response info
        message.update(data)

        self.message = message
Пример #22
0
    def filter_available_terminals(type, filter_condition):
        filter_data = {
            'type': type,
            'is_classify': False,
            'filter_condition': filter_condition
        }

        serializer = common_serializer.TerminalFilterSerializer(
            data=filter_data)

        if serializer.is_valid():
            terminals = serializer.query_result()[0].get('terminals', [])
            return [TerminalInfo(pk=t['value']) for t in terminals]
        else:
            raise natrix_exceptions.ClassInsideException(
                message='Filter available terminals: {}'.format(
                    serializer.format_errors()))
Пример #23
0
    def process(self, stage='dead'):
        """

        :param stage:
        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        try:
            if stage == 'dead':
                self._dead_message_process()

        except natrix_exceptions.BaseException as e:
            # TODO: exception process
            logger.error()
Пример #24
0
    def keep_alive(self, timeout=60):
        try:
            curr_time = time.time()
            last_alert_state = self.state_info.get('last_alert_state')
            curr_state = self.state_info.get('curr_state')
            update_time = self.state_info.get('update_time')

            if curr_time - update_time > timeout:
                self.curr_alert_state = False
                self.time_out()
                return self

            # continuous alive
            if curr_state and last_alert_state:
                self.curr_alert_state = True

                self.alive_continuous()
                return self

            # recovery
            if curr_state and not last_alert_state:
                self.curr_alert_state = True

                self.recovery()
                return self

            # poweroff
            if not curr_state and last_alert_state:
                self.curr_alert_state = False

                self.power_off()
                return self

            # dead continuous
            if not curr_state and not last_alert_state:
                self.curr_alert_state = False

                self.dead_continuous()
                return self

        except Exception as e:
            logger.error('Keep alive with error: {}'.format(e))
            raise natrix_exception.ClassInsideException(message='keep alive failed: {}'.format(e))
Пример #25
0
    def _dead_message_process(self):
        """Dead Message Process

        To process dead message, include:
        - process command status in cache
        - generate message (used to store)
        - store message

        :return:
        """
        if not hasattr(self, '_validated_data'):
            raise natrix_exceptions.ClassInsideException(
                message=u'Must call is_valid before using this method')

        status_res = self._update_command_status()
        if not status_res:
            logger.error('Update command status error, drop this message!')
            return
        self._get_message()
        self.store()
Пример #26
0
    def init_response_queue(channel):
        """初始化'超时未响应'command队列相关配置

        :return:
        """
        try:
            exchange_name = EXCHANGE_RESPONSE
            queue_name = QUEUE_RESPONSE
            routing_key = ROUTE_RESPONSE

            # channel.exchange_declare(exchange=exchange_name, exchange_type='direct')
            # channel.queue_declare(queue=queue_name,
            #                       durable=True)
            # channel.queue_bind(exchange=exchange_name,
            #                    queue=queue_name,
            #                    routing_key=routing_key)
            channel.queue_declare(queue=queue_name, durable=True)
        except Exception as e:
            logger.error(e)
            raise natrix_exceptions.ClassInsideException(message=str(e))
Пример #27
0
    def init_dead_queue(channel):
        """初始化'超时未消费'command队列相关配置

        :param channel:
        :return:
        """
        try:
            exchange_name = EXCHANGE_COMMAND_DEAD
            queue_name = QUEUE_DEAD
            routing_key = ROUTE_DEAD

            channel.exchange_declare(exchange=exchange_name,
                                     exchange_type='direct')
            channel.queue_declare(queue=queue_name, durable=True)
            channel.queue_bind(exchange=exchange_name,
                               queue=queue_name,
                               routing_key=routing_key)

        except Exception as e:
            logger.error(e)
            raise natrix_exceptions.ClassInsideException(message=str(e))
Пример #28
0
 def __init__(self, to=[]):
     if self.valid_to(to):
         self.to = to
     else:
         raise natrix_exceptions.ClassInsideException(
             message=u'Create Notify class with an error parameter')
Пример #29
0
 def set_destination(self, to):
     if isinstance(to, (list, tuple)) and to:
         self.to = to
     else:
         raise natrix_exceptions.ClassInsideException(
             message=u'Create Notify class with an error parameter : to')
Пример #30
0
 def get_curr_state(self):
     if not hasattr(self, 'curr_alert_state'):
         logger.error('The event only exist after you call keep_alive ({}).'.format(self.pk))
         raise natrix_exception.ClassInsideException(message=u'Call get_event before keep_alive.')
     return self.curr_alert_state