예제 #1
0
class TestCentera(object):
    def setup(self):

        self.pool = FPPool(POOL_ADDRESS)
        self.pool.setGlobalOption(FPLibrary.FP_OPTION_EMBEDDED_DATA_THRESHOLD,
                                  100 * 1024)
        self.pool.getPoolInfo()
        # the application will be attached to the clip id
        self.pool.registerApplication("python wrapper read example", "1.0")

    def teardown(self):
        self.pool.close()
예제 #2
0
class TestCentera(object):

    def setup(self):

        self.pool = FPPool(POOL_ADDRESS)
        self.pool.setGlobalOption(FPLibrary.FP_OPTION_EMBEDDED_DATA_THRESHOLD,
                                  100 * 1024)
        self.pool.getPoolInfo()
        # the application will be attached to the clip id
        self.pool.registerApplication("python wrapper read example", "1.0")

    def teardown(self):
        self.pool.close()
예제 #3
0
from Filepool.FPNetException import FPNetException
from Filepool.FPServerException import FPServerException
from Filepool.FPClientException import FPClientException
from Filepool.FPClip import FPClip
from Filepool.FPTag import FPTag
from Filepool.FPFileInputStream import FPFileInputStream
from Filepool.FPBufferInputStream import FPBufferInputStream
from Filepool.FPRetention import FPRetention

try:

  ip = raw_input( "Pool address: " )

  pool = FPPool( ip )

  pool.getPoolInfo()

  print "Cluster ID:\n"
  print "\t" + pool.clusterid + "\n"

  print "Cluster Name:\n"
  print "\t" + pool.clusterName + "\n"

  print "Pool Info Version:\n"
  print "\t" + str(pool.infoVersion) + "\n"

  print "CentraStar Version:\n"
  print "\t" + pool.version + "\n"

  print "Cluster Capacity:\n"
  print "\t" + str(pool.capacity) + "\n"
예제 #4
0
from Filepool.FPLibrary import FPLibrary
from Filepool.FPNetException import FPNetException
from Filepool.FPPool import FPPool
from Filepool.FPServerException import FPServerException
from Filepool.FPTag import FPTag

try:

    ip = raw_input("Pool address: ")

    pool = FPPool(ip)

    pool.setGlobalOption(FPLibrary.FP_OPTION_EMBEDDED_DATA_THRESHOLD,
                         100 * 1024)

    pool.getPoolInfo()

    pool.registerApplication("python wrapper store example", "1.0")

    clip = FPClip(pool, "python store example")

    retention = raw_input("Retention (in seconds): ")

    clip.setRetentionPeriod(long(retention))

    top_handle = clip.getTopTag()

    blob_tag = FPTag(top_handle, "file")

    filename = raw_input("Filename: ")
예제 #5
0
class CenteraConnection(object):
    """
    Manage the clips from a pool.
    :param object:
    :return:
    """
    def __init__(self,
                 pool_ip,
                 options=POOL_DEFAULT_OPTIONS,
                 application=("caspython-centera-library", _version),
                 replace=None):
        """
        Initialize a pool
        :param host:
        :param options:
        :param application: a couple (appname, version) attached to the clip_id
        :param replace: a translation map for replacing unsupported characters
        :return:
        """
        self.log = logging.getLogger(__name__)
        self.pool = FPPool(pool_ip)
        for k, v in options.items():
            self.pool.setGlobalOption(k, v)

        # getPoolInfo sets infos in self.pool.
        self.pool.getPoolInfo()
        # the application will be attached to the clip id
        self.pool.registerApplication(*application)

    def close(self):
        for i in range(3):
            try:
                self.pool.close()
                return
            except FPClientException as e:
                if e.errorString == 'FP_OBJECTINUSE_ERR':
                    self.log.error(
                        "Closing while pool still in use. Sleeping for 1 sec.")
                    sleep(1)
                    continue
                raise

    def put(self, clip_name, files, retention_sec):
        """
        Writes a clip and attached files to worm.

        :param clip_name:
        :param files:
        :param retention_sec:
        :return:
        """
        for f in files:
            self.validate_tag(f)

        with closing(FPClip(self.pool, clip_name, close_retries=3)) as clip:
            clip.setRetentionPeriod(long(retention_sec))
            top_handle = clip.getTopTag()
            for filename in files:
                tag_name = self.clean_tag(filename)
                with closing(FPTag(top_handle, tag_name)) as blob_tag:
                    with closing(FPFileInputStream(filename, 16 * 1024)) as fh:
                        blob_tag.blobWrite(fh.stream, 0)
            clip_id = clip.write()

        return clip_id

    @staticmethod
    def validate_tag(filename):
        """
        Check if a filename is a valid centera tag name.
        :param filename:
        :return: None on succes
        :raises: ValueError if not valid
        """
        for re_m, msg in RE_INVALID_TAGS:
            if re_m.match(CenteraConnection.clean_tag(filename)):
                raise ValueError(msg)

    @staticmethod
    def clean_tag(filename):
        return MYTAG_ + basename(filename)  # .replace("@", "_")

    def get(self, clip_id, tag=None):
        """
        Get a (closed) clip from worm.

        While storing or retrieving tags from worm,
        you may need to set a close_retry.
        :param clip:
        :return:
        """
        with closing(FPClip(self.pool, close_retries=3 if tag else 0)) as clip:
            self._open_or_not_found(clip, clip_id)

            clip.attributes = clip.getDescriptionAttributes()
            if tag:
                clip.tags = [x for x in clip.getTags()]
            return clip

    def get(self, clip_id, tag=None):
        """
        Get a (closed) clip from worm.

        While storing or retrieving tags from worm,
        you may need to set a close_retry.
        :param clip:
        :return:
        """
        with closing(FPClip(self.pool, close_retries=3 if tag else 0)) as clip:
            self._open_or_not_found(clip, clip_id)

            clip.attributes = clip.getDescriptionAttributes()
            if tag:
                clip.tags = [x for x in clip.getTags()]
            return clip

    def download(self, clip_id, tag_name, outfile):
        """

        :param clip_id:
        :param tag_name:
        :param outfile:
        :return: the output file if present. None if not found.
        """
        outfile = normpath(abspath(outfile))
        with closing(FPClip(self.pool, close_retries=3)) as clip:
            self._open_or_not_found(clip, clip_id)

            for blob_id in clip.getBlobs():
                with closing(FPTag(blob_id)) as blob_tag:
                    blob_tag_name = blob_tag.getTagName()
                    if blob_tag_name != tag_name:
                        self.log.debug("Skipping tag: %s when looking for: %s",
                                       blob_tag_name, blob_tag)
                        continue

                    if blob_tag.getBlobSize() < 1:
                        self.log.debug("Empty blob %s" % blob_tag_name)
                        raise ValueError()

                    with closing(FPFileOutputStream(outfile)) as fh:
                        self.log.info("Writing blob %s to %s", blob_tag_name,
                                      outfile)
                        blob_tag.blobRead(fh.stream, 0)

                    return outfile

    def _open_or_not_found(self, clip, clip_id):
        try:
            clip.open(clip_id)
        except FPClientException as e:
            if e.errorString == 'FP_PARAM_ERR':
                raise KeyError(
                    "Wrong parameter detected or ClipID not found: %r" %
                    clip_id)
            raise

    def list(self, start=None, end=None, limit=0):
        """
        Retrieve clips in the given interval.
        NOTE: Once iterated, the result is closed, so you cannot access the
        item any more!


        @see https://www.emc.com/collateral/TechnicalDocument/docu59169.pdf
        :param start:
        :param end:
        :param limit: max number of entries to retrieve. default 0 (unlimited).
        :return:
        """
        # 0 means unlimited.
        if limit == 0:
            limit = -1

        # Open and close FPQuery
        with closing(self._open_query(start, end)) as query:
            status = 0
            while limit != 0:
                # Implements point 5-7 opening and closing the FPQueryResult.
                with closing(FPQueryResult(query.fetchResult(0))) as res:
                    status = res.getResultCode()

                    if status in (FPLibrary.FP_QUERY_RESULT_CODE_END,
                                  FPLibrary.FP_QUERY_RESULT_CODE_ABORT,
                                  FPLibrary.FP_QUERY_RESULT_CODE_ERROR,
                                  FPLibrary.FP_QUERY_RESULT_CODE_INCOMPLETE,
                                  FPLibrary.FP_QUERY_RESULT_CODE_COMPLETE):
                        break
                    elif status == FPLibrary.FP_QUERY_RESULT_CODE_PROGRESS:
                        continue
                    elif status == FPLibrary.FP_QUERY_RESULT_CODE_OK:
                        limit -= 1
                        # Implements point 6
                        yield res

    def _open_query(self,
                    start=None,
                    end=None,
                    qtype=FPLibrary.FP_QUERY_TYPE_EXISTING):
        """
        Open a FPQuery and its associated QueryExpression as stated in the doc.
        The caller is in charge of closing the query.

        Implements points 1, 2, 3, 4, 10 of https://www.emc.com/collateral/TechnicalDocument/docu59169.pdf

        :param start:
        :param end:
        :param qtype:
        :return:
        """
        query_expression = FPQueryExpression()
        query_expression.setType(qtype)
        if start:
            query_expression.setStartTime(
                str_to_seconds(start) * SEC_TO_MILLISEC)
        if end:
            query_expression.setEndTime(str_to_seconds(end) * SEC_TO_MILLISEC)

        try:
            query = FPQuery(self.pool)
            query.open(query_expression)
            return query
        finally:
            query_expression.close()

    def info(self):
        """
        Return a dictionary with essential informations about the centera,
        like free space, replication options, ...
      
        :return: dict
        """

        fields = [
            'clusterid', 'clusterName', 'version', 'infoVersion', 'capacity',
            'freeSpace', 'replicaAddress'
        ]
        ret = dict((f, getattr(self.pool, f)) for f in fields)
        ret['clusterTime'] = self.pool.getClusterTime()
        return ret
예제 #6
0
class CenteraConnection(object):

    """
    Manage the clips from a pool.
    :param object:
    :return:
    """

    def __init__(self, pool_ip, options=POOL_DEFAULT_OPTIONS, application=("caspython-centera-library", _version), replace=None):
        """
        Initialize a pool
        :param host:
        :param options:
        :param application: a couple (appname, version) attached to the clip_id
        :param replace: a translation map for replacing unsupported characters
        :return:
        """
        self.log = logging.getLogger(__name__)
        self.pool = FPPool(pool_ip)
        for k, v in options.items():
            self.pool.setGlobalOption(k, v)

        # getPoolInfo sets infos in self.pool.
        self.pool.getPoolInfo()
        # the application will be attached to the clip id
        self.pool.registerApplication(*application)

    def close(self):
        for i in range(3):
            try:
                self.pool.close()
                return
            except FPClientException as e:
                if e.errorString == 'FP_OBJECTINUSE_ERR':
                    self.log.error("Closing while pool still in use. Sleeping for 1 sec.")
                    sleep(1)
                    continue
                raise

    def put(self, clip_name, files, retention_sec):
        """
        Writes a clip and attached files to worm.

        :param clip_name:
        :param files:
        :param retention_sec:
        :return:
        """
        for f in files:
            self.validate_tag(f)

        with closing(FPClip(self.pool, clip_name, close_retries=3)) as clip:
            clip.setRetentionPeriod(long(retention_sec))
            top_handle = clip.getTopTag()
            for filename in files:
                tag_name = self.clean_tag(filename)
                with closing(FPTag(top_handle,  tag_name)) as blob_tag:
                    with closing(FPFileInputStream(filename, 16 * 1024)) as fh:
                        blob_tag.blobWrite(fh.stream, 0)
            clip_id = clip.write()

        return clip_id

    @staticmethod
    def validate_tag(filename):
        """
        Check if a filename is a valid centera tag name.
        :param filename:
        :return: None on succes
        :raises: ValueError if not valid
        """
        for re_m, msg in RE_INVALID_TAGS:
            if re_m.match(CenteraConnection.clean_tag(filename)):
                raise ValueError(msg)

    @staticmethod
    def clean_tag(filename):
        return MYTAG_ + basename(filename)  # .replace("@", "_")

    def get(self, clip_id, tag=None):
        """
        Get a (closed) clip from worm.

        While storing or retrieving tags from worm,
        you may need to set a close_retry.
        :param clip:
        :return:
        """
        with closing(FPClip(self.pool, close_retries=3 if tag else 0)) as clip:
            self._open_or_not_found(clip, clip_id)

            clip.attributes = clip.getDescriptionAttributes()
            if tag:
                clip.tags = [x for x in clip.getTags()]
            return clip

    def get(self, clip_id, tag=None):
        """
        Get a (closed) clip from worm.

        While storing or retrieving tags from worm,
        you may need to set a close_retry.
        :param clip:
        :return:
        """
        with closing(FPClip(self.pool, close_retries=3 if tag else 0)) as clip:
            self._open_or_not_found(clip, clip_id)

            clip.attributes = clip.getDescriptionAttributes()
            if tag:
                clip.tags = [x for x in clip.getTags()]
            return clip

    def download(self, clip_id, tag_name, outfile):
        """

        :param clip_id:
        :param tag_name:
        :param outfile:
        :return: the output file if present. None if not found.
        """
        outfile = normpath(abspath(outfile))
        with closing(FPClip(self.pool, close_retries=3)) as clip:
            self._open_or_not_found(clip, clip_id)

            for blob_id in clip.getBlobs():
                with closing(FPTag(blob_id)) as blob_tag:
                    blob_tag_name = blob_tag.getTagName()
                    if blob_tag_name != tag_name:
                        self.log.debug(
                            "Skipping tag: %s when looking for: %s", blob_tag_name, blob_tag)
                        continue

                    if blob_tag.getBlobSize() < 1:
                        self.log.debug("Empty blob %s" % blob_tag_name)
                        raise ValueError()

                    with closing(FPFileOutputStream(outfile)) as fh:
                        self.log.info(
                            "Writing blob %s to %s", blob_tag_name, outfile)
                        blob_tag.blobRead(fh.stream, 0)

                    return outfile

    def _open_or_not_found(self, clip, clip_id):
        try:
            clip.open(clip_id)
        except FPClientException as e:
            if e.errorString == 'FP_PARAM_ERR':
                raise KeyError(
                    "Wrong parameter detected or ClipID not found: %r" % clip_id)
            raise

    def list(self, start=None, end=None, limit=0):
        """
        Retrieve clips in the given interval.
        NOTE: Once iterated, the result is closed, so you cannot access the
        item any more!


        @see https://www.emc.com/collateral/TechnicalDocument/docu59169.pdf
        :param start:
        :param end:
        :param limit: max number of entries to retrieve. default 0 (unlimited).
        :return:
        """
        # 0 means unlimited.
        if limit == 0:
            limit = -1

        # Open and close FPQuery
        with closing(self._open_query(start, end)) as query:
            status = 0
            while limit != 0:
                # Implements point 5-7 opening and closing the FPQueryResult.
                with closing(FPQueryResult(query.fetchResult(0))) as res:
                    status = res.getResultCode()

                    if status in (
                        FPLibrary.FP_QUERY_RESULT_CODE_END,
                        FPLibrary.FP_QUERY_RESULT_CODE_ABORT,
                        FPLibrary.FP_QUERY_RESULT_CODE_ERROR,
                        FPLibrary.FP_QUERY_RESULT_CODE_INCOMPLETE,
                        FPLibrary.FP_QUERY_RESULT_CODE_COMPLETE
                    ):
                        break
                    elif status == FPLibrary.FP_QUERY_RESULT_CODE_PROGRESS:
                        continue
                    elif status == FPLibrary.FP_QUERY_RESULT_CODE_OK:
                        limit -= 1
                        # Implements point 6
                        yield res

    def _open_query(self, start=None, end=None, qtype=FPLibrary.FP_QUERY_TYPE_EXISTING):
        """
        Open a FPQuery and its associated QueryExpression as stated in the doc.
        The caller is in charge of closing the query.

        Implements points 1, 2, 3, 4, 10 of https://www.emc.com/collateral/TechnicalDocument/docu59169.pdf

        :param start:
        :param end:
        :param qtype:
        :return:
        """
        query_expression = FPQueryExpression()
        query_expression.setType(qtype)
        if start:
            query_expression.setStartTime(str_to_seconds(start) * SEC_TO_MILLISEC)
        if end:
            query_expression.setEndTime(str_to_seconds(end) * SEC_TO_MILLISEC)

        try:
            query = FPQuery(self.pool)
            query.open(query_expression)
            return query
        finally:
            query_expression.close()

    def info(self):
        """
        Return a dictionary with essential informations about the centera,
        like free space, replication options, ...

        :return: dict
        """

        fields = [ 'clusterid', 'clusterName', 'version', 'infoVersion',
                   'capacity', 'freeSpace', 'replicaAddress' ]
        self.pool.getPoolInfo()
        ret = dict((f, getattr(self.pool, f)) for f in fields )
        ret['clusterTime'] = self.pool.getClusterTime()
        return ret