예제 #1
0
    def put(self, name):
        # Back compatibility with previous endpoint version
        params = request.json.get('params') or request.json
        params_keys = params.keys()
        for param in ['predictor', 'stream_in', 'stream_out']:
            if param not in params_keys:
                return abort(400, 'Please provide "{}"'.format(param))
        if 'integration' not in params_keys and 'connection' not in params_keys:
            return abort(
                400,
                "'integration' in case of local installation and 'connection' in case of cloud are required."
            )

        if 'integration' in params_keys:
            integration = get_db_integration(params['integration'],
                                             request.company_id)
            if integration is None:
                return abort(
                    404, 'Integration "{}" doesn\'t exist'.format(
                        params['integration']))

            if integration['type'] not in STREAM_INTEGRATION_TYPES:
                return abort(
                    400, 'Integration "{}" is not of type [{}]'.format(
                        params['integration'],
                        '/'.join(STREAM_INTEGRATION_TYPES)))

        else:
            if 'type' not in params_keys:
                return abort(404,
                             "'type' parameter is required in case of cloud.")

        if db.session.query(db.Stream).filter_by(
                company_id=request.company_id, name=name).first() is not None:
            return abort(404, 'Stream "{}" already exists'.format(name))

        if db.session.query(db.Predictor).filter_by(
                company_id=request.company_id,
                name=params['predictor']).first() is None:
            return abort(
                404,
                'Predictor "{}" doesn\'t exist'.format(params['predictor']))

        stream = db.Stream(company_id=request.company_id,
                           name=name,
                           integration=params.get('integration'),
                           predictor=params['predictor'],
                           stream_in=params['stream_in'],
                           stream_out=params['stream_out'],
                           anomaly_stream=params.get('anomaly_stream'),
                           learning_stream=params.get('learning_stream'),
                           type=params.get('type'),
                           connection_info=params.get('connection'))

        session.add(stream)
        session.commit()

        return {'success': True}, 200
예제 #2
0
    def _loop(self):
        log.info("INTEGRATION %s: starting", self.name)
        while not STOP_THREADS_EVENT.wait(1.0):
            if self._control_stream is not None:
                # Create or delete streams based on messages from control_stream
                for dct in self._control_stream.read():
                    if 'action' not in dct:
                        log.error(
                            'INTEGRATION %s: no action value found in control record - %s',
                            self.name, dct)
                    else:
                        if dct['action'] == 'create':
                            for k in [
                                    'name', 'predictor', 'stream_in',
                                    'stream_out'
                            ]:
                                if k not in dct:
                                    # Not all required parameters were provided (i.e. stream will not be created)
                                    # TODO: what's a good way to notify user about this?
                                    log.error(
                                        'INTEGRATION %s: stream creating error. not enough data in control record - %s',
                                        self.name, dct)
                                    break
                            else:
                                log.info('INTEGRATION %s: creating stream %s',
                                         self.name, dct['name'])
                                if db.session.query(db.Stream).filter_by(
                                        name=dct['name'],
                                        company_id=self.company_id).first(
                                        ) is None:
                                    stream = db.Stream(
                                        company_id=self.company_id,
                                        name=dct['name'],
                                        integration=self.name,
                                        predictor=dct['predictor'],
                                        stream_in=dct['stream_in'],
                                        stream_out=dct['stream_out'],
                                        anomaly_stream=dct.get(
                                            'stream_anomaly', None),
                                        learning_params=dct.get(
                                            'learning_params', None),
                                        learning_threshold=dct.get(
                                            'learning_threshold', None),
                                    )
                                    db.session.add(stream)
                                    db.session.commit()
                                else:
                                    log.error(
                                        'INTEGRATION %s: stream with this name already exists - %s',
                                        self.name, dct['name'])
                        elif dct['action'] == 'delete':
                            for k in ['name']:
                                if k not in dct:
                                    # Not all required parameters were provided (i.e. stream will not be created)
                                    # TODO: what's a good way to notify user about this?
                                    log.error(
                                        'INTEGRATION %s: unable to delete stream - stream name is not provided',
                                        self.name)
                                    break
                            else:
                                log.error(
                                    'INTEGRATION %s: deleting stream - %s',
                                    self.name, dct['name'])
                                db.session.query(db.Stream).filter_by(
                                    company_id=self.company_id,
                                    integration=self.name,
                                    name=dct['name']).delete()
                                db.session.commit()
                        else:
                            # Bad action value
                            log.error(
                                'INTEGRATION %s: bad action value received - %s',
                                self.name, dct)

            # it is really required to add 'commit' here
            # to avoid case when sessin.query returns previously
            # deleted object
            # https://stackoverflow.com/questions/10210080/how-to-disable-sqlalchemy-caching
            db.session.commit()
            stream_db_recs = db.session.query(db.Stream).filter_by(
                company_id=self.company_id, integration=self.name).all()

            # Stop streams that weren't found in DB
            indices_to_delete = []
            for i, s in enumerate(self._streams):
                if s.name not in map(lambda x: x.name, stream_db_recs):
                    log.info("INTEGRATION %s: stopping stream - %s", self.name,
                             s.name)
                    indices_to_delete.append(i)
                    self._streams[i].stop_event.set()
            self._streams = [
                s for i, s in enumerate(self._streams)
                if i not in indices_to_delete
            ]

            # Start new streams found in DB
            for s in stream_db_recs:
                if s.name not in map(lambda x: x.name, self._streams):
                    log.info("INTEGRATION %s: starting stream - %s", self.name,
                             s.name)
                    self._streams.append(self._make_stream(s))

        log.info("INTEGRATION %s: stopping", self.name)
        for s in self._streams:
            s.stop_event.set()