Esempio n. 1
0
    def take_action(self, parsed_args):
        parsed_args = self.preprocess_args(parsed_args)
        self.requests_client.setup(API_NAME, SERVICE_VERSION)
        self.update_payload(parsed_args)

        destination = parsed_args.destination
        (storage_system, file_path) = self.parse_url(parsed_args.agave_uri)

        headers = self.render_headers(FileStaging, parsed_args)
        rec = copy(file_path,
                   system_id=storage_system,
                   destination=destination,
                   permissive=False,
                   agave=self.tapis_client)

        # Fixes issue where the name of the listed file/directory is not
        # returned by the files service
        if rec['name'] == '.':
            rec['name'] = os.path.basename(rec['path'])
        # Coerce path to absolute path
        rec['path'] = abspath(rec['path'], '/')

        data = []
        for key in headers:
            try:
                val = rec[key]
            except KeyError:
                val = None
            data.append(self.render_value(val))

        return (tuple(headers), tuple(data))
Esempio n. 2
0
def _files_list(directory_path,
                system_id=DEFAULT_SYSTEM_ID,
                limit=DEFAULT_PAGE_SIZE,
                offset=0,
                root_dir='/',
                agave=None):
    """Private function to resiliently list a Tapis files directory
    """
    rooted_directory_path = abspath(directory_path, root_dir)
    logger.info('_files_list: agave://{}{}'.format(system_id, directory_path))
    try:
        return agave.files.list(systemId=system_id,
                                filePath=rooted_directory_path,
                                limit=limit,
                                offset=offset)
    except Exception as err:
        logger.warning('_files_list.error: {}'.format(err))
        raise
Esempio n. 3
0
def _jobs_outputs_list(directory_path,
                       job_uuid,
                       limit=DEFAULT_PAGE_SIZE,
                       offset=0,
                       root_dir='/',
                       agave=None):
    """Private function to resiliently list a Tapis job output directory
    """
    rooted_directory_path = abspath(directory_path, root_dir)
    logger.info('_jobs_outputs_list: agave://{}{}'.format(
        job_uuid, directory_path))
    try:
        return agave.jobs.listOutputs(jobId=job_uuid,
                                      filePath=rooted_directory_path,
                                      limit=limit,
                                      offset=offset)
    except Exception as err:
        logger.warning('_jobs_outputs_list.error: {}'.format(err))
        raise
Esempio n. 4
0
def stat(file_path,
         system_id=DEFAULT_SYSTEM_ID,
         root_dir='/',
         permissive=False,
         agave=None,
         **kwargs):
    """Retrieve attributes for a given path on a Tapis storageSystem

    Arguments:
        file_path (str): The path from which to fetch attributes
        system_id (str, optional): The Tapis storageSystem for file_path
        root_dir (str, optional): Base path on the storageSystem if file_path is relative
        permissive (bool, optional): Whether to raise an Exception on failure
        agave (Agave, optional): An active Tapis client

    Returns:
        dict: A dictionary containing Tapis files API attributes

    Raises:
        HTTPError: A transport or web services error was encountered
        TapisOperationFailed: Some other error prevented the operation
    """
    try:
        try:
            rooted_file_path = abspath(file_path, root_dir)
            resp = agave.files.list(filePath=rooted_file_path,
                                    systemId=system_id,
                                    limit=2)[0]
            return AttrDict(resp)
        except HTTPError as herr:
            handle_http_error(herr)
        except Exception as err:
            raise TapisOperationFailed(
                'Exception encountered with stat#files.list()', err)
    except Exception as err:
        logger.warning(
            'Exception encountered in rsrc_exists(): {}'.format(err))
        if permissive:
            return dict()
        else:
            raise
Esempio n. 5
0
def pems_list(file_path,
              system_id=DEFAULT_SYSTEM_ID,
              limit=DEFAULT_PAGE_SIZE,
              offset=0,
              root_dir='/',
              permissive=False,
              agave=None,
              **kwargs):
    try:
        resp = agave.files.listPermissions(systemId=system_id,
                                           filePath=file_path,
                                           limit=limit,
                                           offset=offset)
        # This fixes an issue with files.listPermissions where the topmost
        # path element is returned as a username. This is probably a service-
        # level bug, rather than an AgavePy defect
        top_dir = splitall(abspath(file_path, root_dir))[1]
        pems = [p for p in resp if p['username'] != top_dir]
        return pems
    except Exception:
        if permissive:
            return []
        else:
            raise
Esempio n. 6
0
def upload(local_file_path,
           system_id,
           destination='/',
           excludes=None,
           includes=None,
           force=False,
           sync=False,
           atomic=False,
           progress=True,
           agave=None):

    (uploaded, skipped, errors, ul_bytes, runtime) = ([], [], [], 0, None)

    if excludes is None:
        excludes = []

    # Compile files to be uploaded
    if progress:
        print_stderr('Finding file(s) to upload...')
    start_time = seconds()
    upload_files = _local_walk(local_file_path)
    elapsed_walk = seconds() - start_time
    msg = 'Found {0} file(s) in {1}s'.format(len(upload_files), elapsed_walk)
    logger.debug(msg)
    if progress:
        print_stderr(msg)

    # Filter out excludes
    # TODO - make sure abs and relpaths are supported
    # TODO - support some kind of wildcard match
    # upload_files = [f for f in upload_files_all if f[0] not in excludes]
    # if progress:
    #     print_stderr('Excluding {0} file(s)'.format(
    #         len(upload_files_all) - len(upload_files)))

    # Compute which, if any, remote directories might need to be created
    # Note that these directory names will be relative to the destination path
    if os.path.isfile(local_file_path):
        dir_parent = os.path.dirname(local_file_path)
        dir_basename = '.'
    else:
        dir_parent = os.path.dirname(local_file_path)
        dir_basename = os.path.basename(local_file_path)
    local_dirs = [
        relpath(os.path.dirname(f[0]).replace(dir_parent, ''))
        for f in upload_files
    ]
    # Before adding the grandparent to set of created dirs, add the destinations to each upload record
    for idx, uf in enumerate(upload_files):
        upload_files[idx].append(os.path.join(destination, local_dirs[idx]))

    # Remove duplicates as each member of create_dirs represents
    # at least one API call
    local_dirs.insert(0, dir_basename)
    create_dirs = []
    for d in local_dirs:
        if d not in create_dirs and d not in ('.', ''):
            create_dirs.append(d)

    # Create the remote directories
    # Do this ahead of time (and manually) to avoid relying on Tapis' files
    # since that service's path handling behavior can be tricky
    for rdir in create_dirs:
        if progress:
            print_stderr('Creating remote directory "{0}"...'.format(rdir))
        makedirs(relpath(rdir),
                 system_id=system_id,
                 destination=abspath(destination),
                 agave=agave)

    # Do the actual uploads
    start_time_all = seconds()
    for ufile in upload_files:
        if progress:
            print_stderr('Uploading {0}...'.format(ufile[0]))
        try:
            _upload(ufile[0],
                    system_id,
                    destination=ufile[3],
                    size=ufile[1],
                    timestamp=ufile[2],
                    includes=includes,
                    excludes=excludes,
                    force=force,
                    sync=sync,
                    agave=agave)
            # TRack uploaded files
            uploaded.append(ufile[0])
            # Track cumulative data size
            ul_bytes = ul_bytes + ufile[1]
        # TODO - implement a separate exception for FileExcluded
        except FileExcludedError as fexc:
            errors.append(fexc)
            skipped.append(ufile[0])
        except FileExistsError as fxerr:
            if sync or force:
                skipped.append(ufile[0])
            else:
                errors.append(fxerr)
        except Exception as exc:
            errors.append(exc)

    elapsed_download = seconds() - start_time_all
    msg = 'Uploaded {0} files in {1}s'.format(len(uploaded), elapsed_download)
    logger.debug(msg)
    if progress:
        print_stderr(msg)

    return uploaded, skipped, errors, ul_bytes, elapsed_download