示例#1
0
    def _create_ref(self, fid):
        """
        Create a reference of timeseries in temporal data database and associate it to fid
        in temporal database for future use.
        Shall be used before create method in case of parallel creation of data (import data via spark for example)

        :param fid: Functional Identifier of the TS in Ikats
        :type fid: str

        :returns: A prepared Timeseries object
        :rtype: Timeseries

        :raises IkatsConflictError: if FID already present in database (use `get` instead of `new`)
        """
        check_is_fid_valid(fid, raise_exception=True)
        try:
            # Check if fid already associated to an existing tsuid
            tsuid = self.dm_client.get_tsuid_from_fid(fid=fid)
            # if fid already exists in database, raise a conflict exception
            raise IkatsConflictError(
                "%s already associated to an existing tsuid: %s" %
                (fid, tsuid))

        except IkatsNotFoundError:
            # Creation of a new tsuid
            metric, tags = self.tsdb_client.gen_metric_tags()
            tsuid = self.tsdb_client.assign_metric(metric=metric, tags=tags)

            # finally importing tsuid/fid pair in non temporal database
            self.dm_client.import_fid(tsuid=tsuid, fid=fid)

            return Timeseries(tsuid=tsuid, fid=fid, api=self.api)
示例#2
0
    def fid2tsuid(self, fid, raise_exception=True):
        """
        Retrieve the TSUID associated to the functional ID param.

        :param fid: the functional Identifier
        :param raise_exception: Allow to specify if the action shall assert if not found or not

        :type fid: str
        :type raise_exception: bool

        :returns: retrieved TSUID value or None if not found
        :rtype: str

        :raises TypeError:  if fid is not str
        :raises IkatsNotFoundError: no match
        """

        check_is_fid_valid(fid=fid)

        # Check if fid already associated to an existing tsuid
        try:
            return self.dm_client.get_tsuid_from_fid(fid=fid)
        except IkatsException:
            if raise_exception:
                raise
            return None
示例#3
0
    def get_tsuid_from_fid(self, fid):
        """
        Retrieve the tsuid associated to the func_id param.

        :param fid: one func_id value
        :type fid: str

        :returns: retrieved tsuid value
        :rtype: str

        :raises TypeError: if unexpected fid parameter
        :raises TypeError: status_code 400 (bad request)
        :raises TypeError: unexpected http status_code
        :raises ValueError: mismatched result: http status_code 404:  not found
        :raises ServerError: http status_code for server errors: 500 <= status_code < 600
        """
        check_is_fid_valid(fid=fid, raise_exception=True)

        # empty result => throws IkatsNotFoundError
        res = self.search_functional_identifiers(criterion_type='funcIds',
                                                 criteria_list=[fid])

        assert (
            isinstance(res, list)
        ), "get_tsuid_from_func_id: failed to retrieve json result as list"
        assert (
            isinstance(res[0], dict)
        ), "get_tsuid_from_func_id: failed to retrieve first item from result list"
        return res[0]['tsuid']
示例#4
0
    def fid(self, value):
        if value is not None:
            check_is_fid_valid(fid=value, raise_exception=True)
            self.__fid = value

            # Try to get existing tsuid
            self.tsuid = self.api.ts.fid2tsuid(fid=self.fid,
                                               raise_exception=False)
示例#5
0
    def import_fid(self, tsuid, fid):
        """
        Import a functional ID into database

        :param tsuid: TSUID identifying the TS
        :param fid: Functional identifier

        :type tsuid: str
        :type fid: str

        :raises TypeError: if *tsuid* not a str
        :raises TypeError: if *fid* not a str

        :raises ValueError: if *tsuid* is empty
        :raises ValueError: if *fid* is empty
        :raises IkatsConflictError: if *fid* exists
        :raises SystemError: if another issue occurs
        """

        # Checks inputs
        check_is_fid_valid(fid=fid, raise_exception=True)
        check_type(value=tsuid,
                   allowed_types=str,
                   var_name="tsuid",
                   raise_exception=True)
        if tsuid == "":
            raise ValueError("tsuid must not be empty")

        response = self.send(root_url=self.session.dm_url + self.root_url,
                             verb=GenericClient.VERB.POST,
                             template=TEMPLATES['import_fid'],
                             uri_params={
                                 'tsuid': tsuid,
                                 'fid': fid
                             })

        # In case of success, web app returns 2XX
        if response.status_code == 200:
            pass
        elif response.status_code == 409:
            raise IkatsConflictError(
                "TSUID:%s - FID already exists (not updated) %s" %
                (tsuid, fid))
        else:
            self.session.log.warning("TSUID:%s - FID %s not created (got %s)",
                                     tsuid, fid, response.status_code)
            raise SystemError("TSUID:%s - FID %s not created (got %s)" %
                              (tsuid, fid, response.status_code))
示例#6
0
    def test_check_is_fid_valid(self):
        """
        Test check_is_fid_valid function
        """

        # FID name not a str
        fid_value = 123
        with self.assertRaises(TypeError):
            check_is_fid_valid(fid=fid_value, raise_exception=True)
        self.assertFalse(
            check_is_fid_valid(fid=fid_value, raise_exception=False))

        # FID too short
        fid_value = "a"
        with self.assertRaises(ValueError):
            check_is_fid_valid(fid=fid_value, raise_exception=True)
        self.assertFalse(
            check_is_fid_valid(fid=fid_value, raise_exception=False))

        # FID too short
        fid_value = ""
        with self.assertRaises(ValueError):
            check_is_fid_valid(fid=fid_value, raise_exception=True)
        self.assertFalse(
            check_is_fid_valid(fid=fid_value, raise_exception=False))

        # FID contains spaces
        fid_value = "FID contains spaces"
        with self.assertRaises(ValueError):
            check_is_fid_valid(fid=fid_value, raise_exception=True)
        self.assertFalse(
            check_is_fid_valid(fid=fid_value, raise_exception=False))

        # Valid FID
        fid_value = "azerty"
        self.assertTrue(
            check_is_fid_valid(fid=fid_value, raise_exception=False))
示例#7
0
    def save(self,
             ts,
             parent=None,
             generate_metadata=True,
             raise_exception=True):
        """
        Import timeseries data points to database or update an existing timeseries with new points

        if *generate_metadata* is set or if no TSUID is present in *ts* object,
        the *ikats_start_date*, *ikats_end_date* and *qual_nb_points* will be
        overwritten by the first point date, last point date and number of points in *ts.data*

        *parent* is the original timeseries where metadata shall be taken from
        (except intrinsic ones, eg. *qual_nb_points*)

        If the timeseries is a new one (object has no tsuid defined), the computation of the metadata is forced

        Returns a boolean status of the action (True means "OK", False means "errors occurred")

        :param ts: Timeseries object containing information about what to create
        :param parent: (optional) Timeseries object of inheritance parent
        :param generate_metadata: Generate metadata (set to False when doing partial import) (Default: True)
        :param raise_exception: Indicates if exceptions shall be raised (True, default) or not (False)

        :type ts: Timeseries
        :type parent: Timeseries
        :type generate_metadata: bool
        :type raise_exception: bool

        :returns: the status of the action
        :rtype: bool

        :raises TypeError: if *ts* is not a valid Timeseries object

        """

        # Input checks
        check_type(ts, Timeseries, "ts", raise_exception=True)
        check_type(parent, [Timeseries, None], "parent", raise_exception=True)
        check_type(generate_metadata,
                   bool,
                   "generate_metadata",
                   raise_exception=True)
        check_is_fid_valid(ts.fid, raise_exception=True)

        try:
            # First, we shall create the TSUID reference (if not provided)
            if ts.tsuid is None:
                ts.tsuid = self._create_ref(ts.fid).tsuid
                # If the TS is fresh, we force the creation of the metadata
                generate_metadata = True

            # Add points to this TSUID
            start_date, end_date, nb_points = self.tsdb_client.add_points(
                tsuid=ts.tsuid, data=ts.data)

            if generate_metadata:
                # ikats_start_date
                self.dm_client.metadata_update(tsuid=ts.tsuid,
                                               name='ikats_start_date',
                                               value=start_date,
                                               data_type=MDType.DATE,
                                               force_create=True)
                ts.metadata.set(name='ikats_start_date',
                                value=start_date,
                                dtype=MDType.DATE)

                # ikats_end_date
                self.dm_client.metadata_update(tsuid=ts.tsuid,
                                               name='ikats_end_date',
                                               value=end_date,
                                               data_type=MDType.DATE,
                                               force_create=True)
                ts.metadata.set(name='ikats_end_date',
                                value=end_date,
                                dtype=MDType.DATE)

                # qual_nb_points
                self.dm_client.metadata_update(tsuid=ts.tsuid,
                                               name='qual_nb_points',
                                               value=nb_points,
                                               data_type=MDType.NUMBER,
                                               force_create=True)
                ts.metadata.set(name='qual_nb_points',
                                value=nb_points,
                                dtype=MDType.NUMBER)

            # Inherit from parent when it is defined
            if parent is not None:
                self.inherit(ts=ts, parent=parent)
        except IkatsException:
            if raise_exception:
                raise
            return False
        return True