john pfeiffer
  • Home
  • Categories
  • Tags
  • Archives

oxygen path object

import os
import logging

from lib.gen_py.cloudfs.ttypes import *


class OxygenPathObject:
    """
    Allows storing extra metadata of Oxygen API Objects (like path or modified timestamp)
    and provides many helper methods for converting between Oxygen API Object types and
    especially useful methods regarding Oxygen top level containers (i.e. Spaces, Volumes)
    """
    oid = None               # universal unique identifier because of o2object.id and o2object.oid
    o2object = None
    path = ''       # path empty = root level
    modified_timestamp = 0

    def __init__( self , oid , o2object , path , modified_timestamp ):
        self.oid = oid            # more control over how objects can be compared (i.e. o2objects are sometimes id and sometimes oid)
        self.o2object = o2object
        self.path = path
        self.modified_timestamp = modified_timestamp

    def __eq__( self , other ):     # TODO: not used and so may be unnecessary work
        if not other:
            return False
        else:
            return self.oid == other.oid

    def __hash__(self):             # TODO: not used and so may be unnecessary work
        return hash( self.oid )

    @staticmethod
    def get_unicode_string( s ):
        if s:
            return s if type(s) is unicode else (s.decode('utf-8') if type(s) is str else unicode(s))
        else:
            return s

    @staticmethod
    def convert_to_local_file_path( local_destination_path , cloud_folder_path , object_name ):
        local_destination_path = os.path.normpath( local_destination_path )

        if cloud_folder_path == '':
            converted_path = ''                               # do not convert blank into '.'
        elif cloud_folder_path[0] == '/':
            stripped_path = cloud_folder_path[1:]       # strip any leading slashes
            converted_path = os.path.normpath( stripped_path )    # i.e. for downloading from the cloud to Windows
        else:
            converted_path = os.path.normpath( cloud_folder_path )

        new_path = os.path.join( converted_path , object_name )      # name is a single string so does not need conversion

        new_absolute_full_local_path = os.path.join( local_destination_path ,  new_path )
        return new_absolute_full_local_path


    @staticmethod
    def convert_space_info_to_api_object( api_space_info_object ):
        """
        ApiSpaceInfo( capacity=0, name='space-name', writableDefault=False, oid='ff8080813cbbeafe013cf496a90e3392',
              ownerOid='ff80808134f2fda80134f75ab6de0108', createdTimestamp=1361313179000L, utilized=0.00048828125,
              ownerOxygenId='John-Enterprise-QA', storageName='Default John-Enterprise-QA Cloud', spaceDescription=None,
              repositoryNodeId='repositorynode3', listed=False )

        ApiObject( canManage=True, sizeInByte=0, name='many-folder-space', modifiedByUserName=None, canWrite=True,
            repositoryNodeServiceId='repositorynode3', modifiedTimestamp=0, createdTimestamp=0, deleted=False, versionId=0,
            ownerOxygenId='John-Enterprise-QA', spaceId='ff8080813cbbeafe013cf496a90e3392', parentId='', createdByUserName=None,
            type=2, id='ff8080813cbbeafe013cf496a90e3392' )
        """
        if not api_space_info_object:
            raise ValueError( "api_space_info_object must exist" )
        api_object = ApiObject( canManage = True , sizeInByte = 0 , name = api_space_info_object.name , canWrite = True ,
                                      repositoryNodeServiceId = api_space_info_object.repositoryNodeId , modifiedTimestamp = 0 ,
                                      createdTimestamp = 0, deleted = False , versionId = 0 , ownerOxygenId = api_space_info_object.ownerOxygenId ,
                                      spaceId = api_space_info_object.oid , parentId = '' , type = ApiObjectType.SPACE , id = api_space_info_object.oid )
        return api_object


    @staticmethod
    def convert_space_object_to_api_object( api_space_object ):
        """
        ApiSpace(ownerUserOid='ff80808134f2fda80134f75ab6de0108', repoNodeServiceId='repositorynode3', managePermitted=True,
        name='many-folder-space', writePermitted=True, ownerLoginId='John-Enterprise-QA', id='ff8080813cbbeafe013cf496a90e3392')

        ApiObject( canManage=True, sizeInByte=0, name='many-folder-space', modifiedByUserName=None, canWrite=True,
            repositoryNodeServiceId='repositorynode3', modifiedTimestamp=0, createdTimestamp=0, deleted=False, versionId=0,
            ownerOxygenId='John-Enterprise-QA', spaceId='ff8080813cbbeafe013cf496a90e3392', parentId='', createdByUserName=None,
            type=2, id='ff8080813cbbeafe013cf496a90e3392' )
        """
        if not api_space_object:
            raise ValueError( "api_space_object must exist" )
        api_object = ApiObject( canManage = api_space_object.managePermitted , sizeInByte = 0 , name = api_space_object.name ,
                                canWrite = api_space_object.writePermitted , repositoryNodeServiceId = api_space_object.repoNodeServiceId ,
                                modifiedTimestamp = 0 , createdTimestamp = 0, deleted = False , versionId = 0 , ownerOxygenId = api_space_object.ownerUserOid ,
                                spaceId = api_space_object.id , parentId = '' , type = ApiObjectType.SPACE , id = api_space_object.id )
        return api_object



    @staticmethod
    def get_account_space_info_listing( agent ):
        if not agent:
            raise ValueError( u"ERROR: agent cannot be null in {}".format( OxygenPathObject.get_account_volume_info_listing.__name__ ) )
        return OxygenPathObject.get_top_level_container_info_listing( agent , 'findAllSpacesInAccount' )


    @staticmethod
    def get_account_volume_info_listing( agent ):
        if not agent:
            raise ValueError( u"ERROR: agent cannot be null in {}".format( OxygenPathObject.get_account_volume_info_listing.__name__ ) )
        return OxygenPathObject.get_top_level_container_info_listing( agent , 'findAllUserVolumesInAccount' )


    @staticmethod
    def get_top_level_container_info_listing( agent , container_type ):
        if not agent:
            raise ValueError( u"ERROR: agent parameter cannot be null in {}()".format( OxygenPathObject.get_top_level_container_info_listing.__name__ ) )
        if not container_type:
            raise ValueError( u"ERROR: container_type parameter is not defined in {}()".format( OxygenPathObject.get_top_level_container_info_listing.__name__ ) )

        full_listing = list()
        index_timestamp = 0
        previous_batch_last_space_id = ''         # to verify when all items have been retrieved
        current_batch = None

        while True:
            if container_type == 'findAllSpacesInAccount':
                try:
                    current_batch = agent.findAllSpacesInAccount( index_timestamp )    # retrieves a batch of ApiSpaceInfo starting from the given createdTimestamp
                except EOFError as error:
                    logging.warn( 'findAllSpacesInAccount() received an EOF from the cloud, retrying' )
                    current_batch = agent.findAllSpacesInAccount( index_timestamp )    # retrieves a batch of ApiSpaceInfo starting from the given createdTimestamp

            elif container_type == 'findAllUserVolumesInAccount':
                try:
                    current_batch = agent.findAllUserVolumesInAccount( index_timestamp )    # retrieves a batch of ApiSpaceInfo starting from the given createdTimestamp
                except EOFError as error:
                    logging.warn( 'findAllSpacesInAccount() received an EOF from the cloud, retrying' )
                    current_batch = agent.findAllUserVolumesInAccount( index_timestamp )    # retrieves a batch of ApiSpaceInfo starting from the given createdTimestamp

            else:
                logging.error( u'list method for container_type is not recognized: {}'.format( container_type ) )

            if not current_batch:
                logging.warn( "None or 0 results returned from the cloud" )
                break        # not sure when nothing is returned but certainly a good reason to exit the loop

            if previous_batch_last_space_id == current_batch[ -1 ].oid:
                logging.info( 'search complete')
                break

            full_listing.extend( current_batch )

            last_space_in_current_batch = current_batch[ -1 ]
            index_timestamp = last_space_in_current_batch.createdTimestamp      # used as a proxy for an iterator to get the next batch
            previous_batch_last_space_id = last_space_in_current_batch.oid            # update the end of loop condition
            logging.debug( u'batch of results synchronized by: {} {}'.format( index_timestamp , previous_batch_last_space_id ) )

        deduplicated_listing = OxygenPathObject.remove_duplicates_from_api_space_info_list( full_listing )
        return deduplicated_listing


    @staticmethod
    def remove_duplicates_from_api_space_info_list( api_space_info_listing ):
        """
        ApiSpaceInfo( capacity=0, name='space-name', writableDefault=False, oid='ff8080813cbbeafe013cf496a90e3392',
        ownerOid='ff80808134f2fda80134f75ab6de0108', createdTimestamp=1361313179000L, utilized=0.00048828125,
        ownerOxygenId='John-Enterprise-QA', storageName='Default John-Enterprise-QA Cloud', spaceDescription='description here',
        repositoryNodeId='repositorynode3', listed=False )
        """
        seen_oid_set = set()
        deduplicated_listing = list()
        for item in api_space_info_listing:
            if item.oid not in seen_oid_set:
                deduplicated_listing.append( item )
                seen_oid_set.add( item.oid )
        return deduplicated_listing



    @staticmethod
    def get_top_level_container_by_name( agent , target_name , container_type = '' ):
        """ matching by name returns the last result from a complete list of all Spaces and Volumes in an Account
            if no type is specified and a Space and Volume have the same name the Space will be returned
            """
        result = None

        if container_type == 'Space':
            space_listing = OxygenPathObject.get_account_volume_info_listing( agent )
            for space in space_listing:
                if space.name == target_name:
                    result = space
        elif container_type == 'Volume':
            volume_listing = OxygenPathObject.get_account_volume_info_listing( agent )
            for volume in volume_listing:
                if volume.name == target_name:
                    result = volume
        else:
            volume_listing = OxygenPathObject.get_account_volume_info_listing( agent )
            for volume in volume_listing:
                if volume.name == target_name:
                    result = volume

            space_listing = OxygenPathObject.get_account_volume_info_listing( agent )
            for space in space_listing:
                if space.name == target_name:
                    result = space
        return result

  • « oxygen scanner
  • oxygen downloader »

Published

Jun 1, 2013

Category

python-oxygencloud-snapshot

~766 words

Tags

  • object 7
  • oxygen 14
  • path 6
  • python 180
  • snapshot 12