Multiple Storage Scenarios
1 1

3 posts in this topic

Hey there again, 

 

its been a while since my last post..

 

We currently exploring, whats the best way to tell a project, thats all its files, components, asset versions are now stored somewhere else. 

The background for this is, that we want to be able to move a project after its creation. For this we could listen to "ftrack.api.session.configure-location" and configure a custom location. But how can access the storage scenario to setup new mount-points?

 

Is it even possible to set the storage scenario via ftrack_api?

 

 

thanks in advance

 

 

Tim

Share this post


Link to post
Share on other sites

What we tried so far...

 

We are getting this error:

ftrack_connect.ui.widget.publisher.Publisher - ERROR - Failed to publish: Failed to transfer component <FileComponent(ccfee77a-266c-4248-9431-bc573e7cc3f4)> data to location <Location("Infected_custom_location", 96865d31-ddb8-4ef9-bbde-79fdc5a7e8dd)> due to error:
    'Session' object has no attribute '__getitem__'
    Transferred component data that may require cleanup: []
Traceback (most recent call last):
  File "c:\python27\lib\site-packages\ftrack_connect-1.1.3-py2.7.egg\ftrack_connect\ui\widget\publisher.py", line 298, in _publish
    component, source=origin_location
  File "c:\python27\lib\site-packages\ftrack_python_api-1.4.0-py2.7.egg\ftrack_api\entity\location.py", line 78, in add_component
    [component], sources=source, recursive=recursive
  File "c:\python27\lib\site-packages\ftrack_python_api-1.4.0-py2.7.egg\ftrack_api\entity\location.py", line 211, in add_components
    transferred=transferred
LocationError: Failed to transfer component <FileComponent(ccfee77a-266c-4248-9431-bc573e7cc3f4)> data to location <Location("Infected_custom_location", 96865d31-ddb8-4ef9-bbde-79fdc5a7e8dd)> due to error:
    'Session' object has no attribute '__getitem__'
    Transferred component data that may require cleanup: []
2018-08-09 13:23:25,811 - root - ERROR - Logging an uncaught exception
Traceback (most recent call last):
  File "c:\python27\lib\site-packages\ftrack_connect-1.1.3-py2.7.egg\ftrack_connect\asynchronous.py", line 21, in exceptHookWrapper
    method(*args, **kwargs)
  File "c:\python27\lib\site-packages\ftrack_connect-1.1.3-py2.7.egg\ftrack_connect\ui\widget\publisher.py", line 298, in _publish
    component, source=origin_location
  File "c:\python27\lib\site-packages\ftrack_python_api-1.4.0-py2.7.egg\ftrack_api\entity\location.py", line 78, in add_component
    [component], sources=source, recursive=recursive
  File "c:\python27\lib\site-packages\ftrack_python_api-1.4.0-py2.7.egg\ftrack_api\entity\location.py", line 211, in add_components
    transferred=transferred
LocationError: Failed to transfer component <FileComponent(ccfee77a-266c-4248-9431-bc573e7cc3f4)> data to location <Location("Infected_custom_location", 96865d31-ddb8-4ef9-bbde-79fdc5a7e8dd)> due to error:
    'Session' object has no attribute '__getitem__'
    Transferred component data that may require cleanup: []

 

We setup a customized version of the Resolver.py, doing this:

 

The Resolver.py listens to:

session.event_hub.subscribe('topic=ftrack.storage-scenario.activate', resolver.activate_storage_scenario)
session.event_hub.subscribe('topic=ftrack.api.session.configure-location', resolver.configure_location)
session.event_hub.subscribe('topic=ftrack.location.request-resolve and source.user.username="{0}"'.format(session.api_user), resolver)

 

in activate_storage_scenario we do the following: 

    def activate_storage_scenario(self, event):
        self.logger.info('activate_storage_scenario was called...\n{0}'.format(event))
        scenario_name = 'Infected_custom_storage_scenario'
        location = self.get_or_create_location()
        mount_points = {}
        mount_points['windows'] = '\\\\infsan\\FTrack'
        mount_points['osx'] = '/Volumes/FTrack'
        mount_points['linux'] = '/mnt/FTrack'
        setting_value = json.dumps({
            'scenario': scenario_name,
            'data': {
                'location_id': location['id'],
                'location_name': location['name'],
                'accessor': {
                    'mount_points': {
                        'linux': mount_points['linux'],
                        'osx': mount_points['osx'],
                        'windows': mount_points['windows']
                    }
                }
            }
        })
        self.storage_scenario['value'] = setting_value
        self.session.commit()
        # Broadcast an event that storage scenario has been configured.
        self.session.event_hub.publish(ftrack_api.event.base.Event(topic='ftrack.storage-scenario.configure-done'))
        self.logger.info('activate_storage_scenario - done. ')

This is essentially a copy of the code from "_centralized_storage_scenario.py" from the ftrack_api, but changed to our needs (is ths propably the cause for the error?)

 

configure_location does this:

    def configure_location(self, event):
        # location = event['data']['session'].query('Location where name is "studio.central-storage-location"').one()
        # location = event['data']['session'].query('Location where name is "Infected_custom_location"').one()
        location = self.get_or_create_location()
        location.structure = InfectedStructure.Structure.InfectedStructure(session=event['data']['session'])
        location.accessor = ftrack_api.accessor.disk.DiskAccessor(prefix='')
        location.priority = 0
        self.logger.info('configure_location - done. ')

 

When the Resolver gets called, it executes this:

    def __call__(self, event):
        self.session.reset()
        self.logger.info('Resolver got called with event: {0}'.format(event))
        #event['data']['locationName'] = 'Infected_custom_location' # override location name...
        location_name = event['data'].get('locationName')
        component_id = event['data']['componentId']
        location = None
        if location_name is None:
            component = self.session.get('Component', component_id)
            self.logger.info('component keys: {0}'.format(component.keys()))
            location = self.session.pick_location(component)
            self.logger.error( u'No location name given, picked location {0!r} for {1!r}.'.format( location, component ) )
            if location is None:
                self.logger.error(u'Location cannot be found')
                return
            location_name = location['name']
        if not self.filter_locations(location_name):
            self.logger.error( u'Skipping resolve for location {0}.'.format( location_name ) )
            return    
        if location is None:
            location = self.session.query( 'Location where name is "{0}"'.format( location_name ) ).one()       
        if not location.accessor:
            self.logger.error(u'Skipping resolve for location without accessor: {0!r}.'.format( location ) )
            return
        component = self.session.get('Component', component_id)
        resource_identifier = location.get_resource_identifier(component)
        path = None
        try:
            project = self.getProjectFromComponent(component)
            if not project: 
                self.logger.info('no project found to load location_mapping')
                return
            self.logger.info('PROJECT_Location: {0}'.format(project['custom_attributes']['PROJECT_Location'][0]))
            location.accessor.prefix = location.structure.location_mapping[project['custom_attributes']['PROJECT_Location'][0]]
            path = location.accessor.get_filesystem_path(resource_identifier)
        except ftrack_api.exception.AccessorUnsupportedOperationError:
            try:
                path = location.accessor.get_url(resource_identifier)
            except ftrack_api.exception.AccessorUnsupportedOperationError:
                self.logger.error(u'Unable to get URL from accessor. Unsupported operation')
                pass
        if path is None:
            raise ValueError(u'Could not resolve {0!r} and {1!r} to a file system path or URL.'.format( component, location ) )
            self.logger.error(u'Could not resolve {0!r} and {1!r} to a file system path or URL.'.format( component, location ))
        self.logger.info(u'Successfully resolved {0!r}.'.format(path))
        return dict(path=path)

 

and finally get_or_create_location does this:

    def get_or_create_location(self):
        location = self.session.ensure('Location',
        {
            'name': 'Infected_custom_location',
            'label': 'Infected_custom_location_label',
            'description': ('Infected_custom_location_description')
        })
        return location

 

 

I hope this is all information regarding the error above. If anybody has an idea, some insights or has seen this before -> let us know. Until then, we're trying to get our head around this...

 

Thanks

 

 

Tim

Share this post


Link to post
Share on other sites

ok. we found it. The error was in an other class and hard to find..(ignored whitespace and indentation, which was ignored by the python interpreter). It looks like, that errors, when happening in custom accessors and or structures, arent addressed properly by error-debug-log. 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
1 1