예제 #1
0
 def get(self, path):
     query = self.sess.query(Collection).filter(Collection.name == path)
     try:
         result = query.one()
     except NoResultFound:
         raise CollectionDoesNotExist()
     return iRODSCollection(self, result)
예제 #2
0
 def get(self, ipath):
     if ipath not in self.collections:
         fname = os.path.join(self.session.collection_dir,
                              ipath.replace('/', '#') + ".json")
         if os.path.isfile(fname):
             with open(fname) as fp:
                 coll = iRodsCollection(self.session,
                                        ipath,
                                        json.load(fp))
                 self.collections[ipath] = coll
         else:
             raise CollectionDoesNotExist(ipath)
     return self.collections[ipath]
예제 #3
0
 def get(self, path):
     path = iRODSCollection.normalize_path(path)
     filters = [Collection.name == path]
     # if a ticket is supplied for this session, try both without and with DataObject join
     repeats = (True,False) if hasattr(self.sess,'ticket__') \
          else (False,)
     for rep in repeats:
         query = self.sess.query(Collection).filter(*filters)
         try:
             result = query.one()
         except NoResultFound:
             if rep:
                 filters += [DataObject.id != 0]
                 continue
             raise CollectionDoesNotExist()
         return iRODSCollection(self, result)
    def move(self, iterator, irods_path, clobber=True, interactive=False,
             verbose=False):
        """ Moving or renaming iRODS data objects and/or collections,
        similar to the UNIX `mv` command.

        Raises an CollectionDoesNotExist if the iterator corresponds to more
        than one item and the irods_path destination does not correspond to an
        existing collection.

        Examples:

        >>> session.bulk.move('tmpfiles*', '~/tmpdir/', verbose=True)
        >>> session.bulk.move('./parent/dirname', './parent/dirname_new')

        Arguments:

        iterator: iterator or str
            Defines which items are subject to the bulk operation.
            Can be an iterator (e.g. using search_manager.find())
            or a string (which will be used to construct a
            search_manager.iglob() iterator). Matching data objects
            and collections will be moved to the new path.

        irods_path: str (default: '.')
            The (absolute or relative) path on the local file system
            where the data objects and collections will moved to.

        clobber: bool (default: True)
            Whether to overwrite existing data objects.

        interactive: bool (default: False)
            Whether to prompt for permission before overwriting
            existing data objects. If True, the value of the 'clobber'
            argument is ignored.

        verbose: bool (default: False)
            Whether to print more output.
        """
        def move_one(src, dest):
            # Move/renames a single item
            src_abs = self.session.path.get_absolute_irods_path(src)
            dest_abs = self.session.path.get_absolute_irods_path(dest)

            src_is_collection = self.session.collections.exists(src_abs)
            dest_is_object = self.session.data_objects.exists(dest_abs)
            kind = 'collection' if src_is_collection else 'data object'

            ok = True

            if not clobber:
                ok = not dest_is_object

            if interactive:
                ok = confirm('move', kind, src_abs + ' to ' + dest_abs)

            if ok:
                self.log('Moving %s %s to destination %s' % \
                         (kind, src_abs, dest_abs), verbose)

                if src_is_collection:
                    if dest_is_object:
                        msg = 'Cannot overwrite obj %s with coll %s'
                        raise OperationNotSupported(msg % (dest_abs, src_abs))
                    else:
                        self.session.collections.move(src_abs, dest_abs)
                else:
                    self.session.data_objects.move(src_abs, dest_abs)
            else:
                self.log('Skipped moving %s %s to destination %s' % \
                         (kind, src_abs, dest_abs), verbose)


        if isinstance(iterator, str):
            iterator = self.session.search.iglob(iterator)

        try:
            previous_item = next(iterator)
        except StopIteration:
            raise StopIteration('Iterator yields no objects or collections')

        dest = self.session.path.get_absolute_irods_path(irods_path)

        item = None
        for item in iterator:
            # There is more than one item, so irods_path needs
            # to be an existing collection
            if not self.session.collections.exists(dest):
                raise CollectionDoesNotExist(dest)

            move_one(previous_item, dest)
            previous_item = item

        if item is not None:
            move_one(item, dest)
        else:
            # The iterator only held 1 item originally,
            # and it hasn't been processed yet
            move_one(previous_item, dest)

        return
    def put(self, iterator, irods_path='.', recurse=False, clobber=True,
            interactive=False, verbose=False, create_options={}, **options):
        """ Copy local files and/or folders to the iRODS server,
        in a manner that resembles the UNIX 'cp' command.

        Examples:

        >>> session.bulk.put('tmpdir*', recurse=True)
        >>> session.bulk.put('~/local_db/*.xyz', irods_path='./irods_db/')

        Arguments:

        iterator: iterator or str
            Defines which items are subject to the bulk operation.
            Can be an iterator (e.g. using search_manager.find())
            or a string (which will be used to construct a
            in search_manager.iglob() iterator). Matching files on the
            local machine (and, if used recursively, directories) will
            be copied to the iRODS server.

        irods_path: str (default: '.')
            The (absolute or relative) path on the iRODS file system
            where the local files and folders will be copied to.

        recurse: bool (default: False)
            Whether to use recursion, meaning that also matching folders
            and their files and subfolders will be copied to the iRODS server.

        clobber: bool (default: True)
            Whether to overwrite existing data objects.

        interactive: bool (default: False)
            Whether to prompt for permission before overwriting
            existing data objects. If True, the value of the 'clobber'
            argument is ignored.

        verbose: bool (default: False)
            Whether to print more output.

        create_options: dict (default: {})
            Additional options to be passed on to PRC's
            collections.create() method.

        options: (any remaining keywords arguments)
            Additional options to be passed on to PRC's
            data_objects.put() method.
        """
        if type(iterator) is str:
            iterator = glob.iglob(iterator)

        dest = self.session.path.get_absolute_irods_path(irods_path)

        if not self.session.collections.exists(dest):
            raise CollectionDoesNotExist(dest)

        for item in iterator:
            local_path = item.rstrip('/')
            path = os.path.join(dest, os.path.basename(local_path))

            if os.path.isdir(local_path):
                if recurse:
                    if not self.session.collections.exists(path):
                        self.log('Creating collection: %s' % path, verbose)
                        self.session.collections.create(path, recurse=True,
                                                        **create_options)

                    self.put(local_path + '/*', irods_path=path, recurse=True,
                             clobber=clobber, interactive=interactive,
                             create_options=create_options, verbose=verbose,
                             **options)
                else:
                    self.log('Skipping collection %s (no recursion)' % \
                             local_path, verbose)

            elif os.path.isfile(local_path):
                object_exists = self.session.data_objects.exists(path)

                ok = True

                if not clobber:
                    ok = not object_exists

                if interactive:
                    ok = confirm('put', 'file',
                                 local_path +' in collection ' + dest)

                if ok:
                    self.log('Putting file %s in collection %s' % \
                             (local_path, dest), verbose)
                    self.session.data_objects.put(local_path, dest + '/',
                                                  **options)
                else:
                    self.log('Skipped putting file %s in collection %s' % \
                             (local_path, dest), verbose)
예제 #6
0
    def pullFile(self, file_path, custom_name, user_name, galaxy_params):
        """
		This function pulls a given file from a iRODS server

		@param	file_path, the path to the file in iRODS
		@param	custom_name, a custom name for the file in the Galaxy history
		@param	user_name, the name for the galaxy user
		@param	galaxy_params, different params extracted from Galaxy environment
		@return True if finished successfully
		@throws CollectionDoesNotExist if the file path does not exist
		        or if it is not readable for the current user
		"""
        #Step 1. Check if the origin directory exists and is valid for current user
        file_path = file_path.split("/")
        if len(file_path) < 2:
            raise CollectionDoesNotExist("File path is not valid. The path " +
                                         "/".join(file_path) +
                                         " was not found in iRODS.")

        fileName = file_path[-1]
        file_path = "/".join(file_path[0:len(file_path) - 1]) + "/"

        valid = self.checkDestinationPermissions(file_path, user_name,
                                                 fileName)
        if valid == -1:
            raise CollectionDoesNotExist("File path not valid. The path " +
                                         file_path +
                                         " does not exist in iRODS.")
        elif valid == 1:
            raise CollectionDoesNotExist(
                "File path not valid. The directory " + file_path +
                " in iRODS is not readable for current user.")
        elif valid != 2:
            raise CollectionDoesNotExist("Unable to find the file '" +
                                         fileName + "' in directory " +
                                         file_path + " in iRODS.")

        print("Copying the file from iRODS...")

        #Step 2. Copy the file content to a temporal file
        obj = self.session.data_objects.get(file_path + fileName)
        with obj.open('r+') as input:
            with open(custom_name, "w") as output:
                output.write(input.read())  #TODO: write to a temporal file?
        output.close()
        input.close()

        print("Registering the file in Galaxy...")

        file_content = {
            "uuid": None,
            "file_type": galaxy_params["file_type"],
            "space_to_tab": False,
            "dbkey": "?",
            "to_posix_lines": True,
            "ext": galaxy_params["file_type"],
            "path": os.path.abspath(output.name),
            "in_place": True,
            "dataset_id": galaxy_params["job_id"],
            "type": "file",
            "is_binary": False,  #TODO: GET FROM METADATA
            "link_data_only": "copy_files",
            "name": custom_name
        }

        with open("temporal.json", "w") as fileParams:
            fileParams.write(json.dumps(file_content))
        fileParams.close()

        #Step 3. Call to Galaxy's upload tool
        command = [
            "python",
            galaxy_params["GALAXY_ROOT_DIR"] + "/tools/data_source/upload.py",
            galaxy_params["GALAXY_ROOT_DIR"],
            galaxy_params["GALAXY_DATATYPES_CONF_FILE"],
            os.path.abspath(fileParams.name), galaxy_params["job_id"] + ":" +
            galaxy_params["output_dir"] + ":" + galaxy_params["output_file"]
        ]

        # TODO: Check return code from call to subprocess
        subprocess.call(command)

        return True
예제 #7
0
    def pushFile(self, origin_file, destination_dir, file_name, overwrite,
                 metadata):
        """
		This function push a given file to the iRODS server

		@param	origin_file, the dataset to save
		@param	destination_dir, path to destination dir in iRODS
		@param	file_name, the name for the file in Galaxy
		@param	overwrite, if true existing files with same name will be replaced
		@param	metadata, the metadata for the file (including provenance)
		@return True if finished successfully
		@throws IOError if the file does not exist in the Galaxy server
		@throws CollectionDoesNotExist if the destination directory does not exist
		        or if it is not writable for the current user
		"""
        #Step 1. Check if the origin file is valid
        import os.path
        if not os.path.isfile(origin_file):
            raise IOError("File not found exception: file " + origin_file +
                          " was not found in server.")

        #Step 2. Check if the destination directory exists and is valid for current user
        valid = self.checkDestinationPermissions(destination_dir,
                                                 metadata["user_name"],
                                                 file_name)
        if valid == -1:
            raise CollectionDoesNotExist(
                "Destination directory not valid. The path " +
                destination_dir + " was not found in iRODS.")
        if valid == 1:
            raise CollectionDoesNotExist(
                "Destination directory not valid. The directory " +
                destination_dir +
                " in iRODS is not writable for current user.")

        #Step 3. If the file already exists and the overwrite option is false, get the new name
        if overwrite == False and valid == 2:
            aux_fileName = file_name
            i = 0
            while valid == 2:
                print("File " + aux_fileName +
                      " already exits. Generating new name.")
                aux_fileName = file_name.split(".")[0]
                try:
                    extension = file_name.split(".")[1]
                except Exception:
                    extension = ""
                i += 1
                aux_fileName = aux_fileName + "_" + str(i) + "." + extension
                print("New name is " + aux_fileName)

                valid = self.checkDestinationPermissions(
                    destination_dir, metadata["user_name"], aux_fileName)
            file_name = aux_fileName

        #Step 4. Send the file to iRODS
        self.copyFileToIRODS(destination_dir, origin_file, file_name, metadata)

        #Step 5. Set the metadata for the file
        self.setFileMetadata(destination_dir, file_name, metadata)

        return True
예제 #8
0
    def get_collection_tree(self, base, path, sessions_cleanup=True):
        """
        Lists the folders and files attributes at the input 'path'

        Parameters
        ----------
        base : str
            The base path to validate ; eg. P000000001/C000000001
        path : str
            The collection's id; eg. P000000001/C000000001/SubFolder1/Experiment1/
        sessions_cleanup: bool
            If true, the session will be closed after retrieving the values.

        Returns
        -------
        dict
            The folders and files attributes at the requested path
        """
        output = []
        base_path = "/nlmumc/projects/" + base
        absolute_path = "/nlmumc/projects/" + path

        if not is_safe_path(base_path, absolute_path):
            raise CAT_NO_ACCESS_PERMISSION

        collection = self.session.collections.get(absolute_path)
        for coll in collection.subcollections:
            # query extra collection info: ctime
            query = self.session.query(iRODSCollection).filter(
                iRODSCollection.id == coll.id)
            try:
                result = query.one()
            except NoResultFound:
                raise CollectionDoesNotExist()

            name = irods_basename(result[iRODSCollection.name])
            ctime = result[iRODSCollection.create_time]
            relative_path = path + "/" + name

            folder_node = {
                "name": name,
                "path": relative_path,
                "type": "folder",
                "size": "--",
                "rescname": "--",
                "ctime": ctime.strftime("%Y-%m-%d %H:%M:%S"),
            }

            output.append(folder_node)

        for data in collection.data_objects:
            # query extra data info: ctime
            query = self.session.query(DataObject).filter(
                DataObject.id == data.id)
            try:
                result = query.first()
            except NoResultFound:
                raise DataObjectDoesNotExist()

            ctime = result[DataObject.create_time]
            relative_path = path + "/" + data.name

            data_node = {
                "name": data.name,
                "path": relative_path,
                "type": "file",
                "size": data.size,
                "rescname": data.resource_name,
                "offlineResource": data.resource_name == "arcRescSURF01",
                "ctime": ctime.strftime("%Y-%m-%d %H:%M:%S"),
            }

            output.append(data_node)

        if sessions_cleanup:
            self.session.cleanup()

        return output