Esempio n. 1
0
    def create_requirements_file(self, execpath="pipreqs"):
        """Create python requirements txt file for the project

        Parameters
        ----------
        execpath : str, optional
            execpath for the pipreqs command to form requirements.txt file
            (default is "pipreqs")

        Returns
        -------
        str
            absolute filepath for requirements file

        Raises
        ------
        EnvironmentDoesNotExist
            no python requirements found for environment
        EnvironmentRequirementsCreateException
            error in running pipreqs command to extract python requirements
        """
        try:
            subprocess.check_output([execpath, self.filepath, "--force"],
                                    cwd=self.filepath).strip()
            requirements_filepath = os.path.join(self.filepath,
                                                 "requirements.txt")
        except Exception as e:
            raise EnvironmentRequirementsCreateException(
                __("error", "controller.environment.requirements.create",
                   str(e)))
        if open(requirements_filepath, "r").read() == "\n":
            raise EnvironmentDoesNotExist()
        return requirements_filepath
Esempio n. 2
0
    def delete(self, environment_id):
        """Delete all traces of an environment

        Parameters
        ----------
        environment_id : str
            environment object id to remove

        Returns
        -------
        bool
            True if success

        Raises
        ------
        EnvironmentDoesNotExist
            if the specified Environment does not exist.
        """
        self.environment_driver.init()
        if not self.exists(environment_id):
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.delete", environment_id))
        # Remove file collection
        environment_obj = self.dal.environment.get_by_id(environment_id)
        file_collection_deleted = self.file_collection.delete(
            environment_obj.file_collection_id)
        # Remove artifacts associated with the environment_driver
        environment_artifacts_removed = self.environment_driver.remove(
            environment_id, force=True)
        # Delete environment_driver object
        delete_success = self.dal.environment.delete(environment_obj.id)

        return file_collection_deleted and environment_artifacts_removed and \
               delete_success
Esempio n. 3
0
    def create(self, path=None, output_path=None, language=None):
        if not path:
            path = os.path.join(self.filepath, "Dockerfile")
        if not output_path:
            directory, filename = os.path.split(path)
            output_path = os.path.join(directory, "datmo" + filename)
        if not language:
            language = "python3"

        requirements_filepath = None
        if not os.path.isfile(path):
            if language == "python3":
                # Create requirements txt file for python
                requirements_filepath = self.create_requirements_file()
                # Create Dockerfile for ubuntu
                path = self.create_default_dockerfile(
                    requirements_filepath=requirements_filepath,
                    language=language)
            else:
                raise EnvironmentDoesNotExist(
                    __("error",
                       "controller.environment.driver.docker.create.dne",
                       path))
        if os.path.isfile(output_path):
            raise FileAlreadyExistsException(
                __("error",
                   "controller.environment.driver.docker.create.exists",
                   output_path))
        success = self.form_datmo_definition_file(
            input_definition_path=path, output_definition_path=output_path)

        return success, path, output_path, requirements_filepath
Esempio n. 4
0
 def update(self, environment_id, name=None, description=None):
     """Update the environment metadata"""
     if not self.exists(environment_id):
         raise EnvironmentDoesNotExist()
     update_environment_input_dict = {"id": environment_id}
     if name:
         update_environment_input_dict['name'] = name
     if description:
         update_environment_input_dict['description'] = description
     return self.dal.environment.update(update_environment_input_dict)
Esempio n. 5
0
    def setup(self, options, definition_path):
        environment_type = options.get("environment_type", None)
        environment_framework = options.get("environment_framework", None)
        environment_language = options.get("environment_language", None)
        environment_types = self.get_environment_types()
        if environment_type not in environment_types:
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.driver.docker.setup.dne",
                   environment_type))
        available_environment_info = self.get_supported_frameworks(
            environment_type)
        available_environments = [
            item[0] for item in available_environment_info
        ]
        if environment_framework not in available_environments:
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.driver.docker.setup.dne",
                   environment_framework))
        available_environment_languages = self.get_supported_languages(
            environment_type, environment_framework)
        if available_environment_languages and environment_language not in available_environment_languages:
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.driver.docker.setup.dne",
                   environment_language))

        # Validate the given definition path exists
        if not os.path.isdir(definition_path):
            raise PathDoesNotExist()
        # To setup the environment definition file
        definition_filepath = os.path.join(definition_path, "Dockerfile")
        with open(definition_filepath, "wb") as f:
            if environment_language:
                f.write(
                    to_bytes("FROM datmo/%s:%s-%s%s%s" %
                             (environment_framework, environment_type,
                              environment_language, os.linesep, os.linesep)))
            else:
                f.write(
                    to_bytes("FROM datmo/%s:%s%s%s" %
                             (environment_framework, environment_type,
                              os.linesep, os.linesep)))
        return True
Esempio n. 6
0
    def build(self, environment_id, workspace=None):
        """Build environment from definition file

        Parameters
        ----------
        environment_id : str
            environment object id to build
        workspace : str
            workspace to be used
        Returns
        -------
        bool
            returns True if success

        Raises
        ------
        EnvironmentDoesNotExist
            if the specified Environment does not exist.
        """
        self.environment_driver.init()
        if not self.exists(environment_id):
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.build", environment_id))
        environment_obj = self.dal.environment.get_by_id(environment_id)
        file_collection_obj = self.dal.file_collection.\
            get_by_id(environment_obj.file_collection_id)
        # TODO: Check hardware info here if different from creation time
        # Add in files for that environment id
        environment_definition_path = os.path.join(self.home,
                                                   file_collection_obj.path)
        # Copy to temp folder and remove files that are datmo specific
        _temp_env_dir = get_datmo_temp_path(self.home)
        self.file_driver.copytree(environment_definition_path, _temp_env_dir)
        # get definition filepath for the temp folder
        environment_definition_filepath = os.path.join(
            _temp_env_dir, environment_obj.definition_filename)
        try:
            # Build the Environment with the driver
            self.spinner.start()
            result = self.environment_driver.build(
                environment_id,
                path=environment_definition_filepath,
                workspace=workspace)
        finally:
            self.spinner.stop()
        # Remove both temporary directories
        shutil.rmtree(_temp_env_dir)
        return result
Esempio n. 7
0
    def setup(self, options, definition_path):
        name = options.get("name", None)
        available_environments = self.get_supported_environments()
        # Validate that the name exists
        if not name or name not in [n for n, _ in available_environments]:
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.driver.docker.setup.dne",
                   name))

        # Validate the given definition path exists
        if not os.path.isdir(definition_path):
            raise PathDoesNotExist()
        # To setup the environment definition file
        definition_filepath = os.path.join(definition_path, "Dockerfile")
        with open(definition_filepath, "wb") as f:
            f.write(to_bytes("FROM datmo/%s\n\n" % name))
        return True
Esempio n. 8
0
    def create(self, path=None, output_path=None):
        if not path:
            path = os.path.join(self.filepath, "Dockerfile")
        if not output_path:
            directory, filename = os.path.split(path)
            output_path = os.path.join(directory, "datmo" + filename)
        if not os.path.isfile(path):
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.driver.docker.create.dne",
                   path))
        if os.path.isfile(output_path):
            raise FileAlreadyExistsError(
                __("error",
                   "controller.environment.driver.docker.create.exists",
                   output_path))
        success = self.create_datmo_definition(
            input_definition_path=path, output_definition_path=output_path)

        return success, path, output_path
Esempio n. 9
0
    def build(self, environment_id):
        """Build environment from definition file

        Parameters
        ----------
        environment_id : str
            environment object id to build

        Returns
        -------
        bool
            returns True if success

        Raises
        ------
        EnvironmentDoesNotExist
            if the specified Environment does not exist.
        """
        self.environment_driver.init()
        if not self.exists(environment_id):
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.build", environment_id))
        environment_obj = self.dal.environment.get_by_id(environment_id)
        file_collection_obj = self.dal.file_collection.\
            get_by_id(environment_obj.file_collection_id)
        # TODO: Check hardware info here if different from creation time
        # Build the Environment with the driver
        datmo_definition_filepath = os.path.join(
            self.home, file_collection_obj.path,
            "datmo" + environment_obj.definition_filename)
        try:
            self.spinner.start()
            result = self.environment_driver.build(
                environment_id, path=datmo_definition_filepath)
        finally:
            self.spinner.stop()
        return result
Esempio n. 10
0
    def create(self, dictionary, save_hardware_file=True):
        """Create an environment

        Parameters
        ----------
        dictionary : dict
            optional values to populate required environment entity args
                paths : list, optional
                    list of absolute or relative filepaths and/or dirpaths to collect with destination names
                    (e.g. "/path/to/file>hello", "/path/to/file2", "/path/to/dir>newdir")
                    (default if none provided is to pull from project environment folder and project root. If none found create default definition)
                name : str, optional
                    name of the environment
                    (default is None)
                description : str, optional
                    description of the environment
                    (default is None)
        save_hardware_file : bool
            boolean to save hardware file along with other files
            (default is True to save the file and create distinct hashes based on software and hardware)

        Returns
        -------
        Environment
            returns an object representing the environment created

        Raises
        ------
        EnvironmentDoesNotExist
            if there is no environment found after given parameters and defaults are checked
        PathDoesNotExist
            if any source paths provided do not exist
        """
        # Validate Inputs
        create_dict = {"model_id": self.model.id}
        create_dict["driver_type"] = self.environment_driver.type

        validate("create_environment", dictionary)

        # Create temp environment folder
        _temp_env_dir = get_datmo_temp_path(self.home)

        # Step 1: Populate a path list from the user inputs in a format compatible
        # with the input of the File Collection create function
        paths = []

        # a. add in user given paths as is if they exist
        if "paths" in dictionary and dictionary['paths']:
            paths.extend(dictionary['paths'])

        # b. if there exists projet environment directory AND no paths exist, add in absolute paths
        if not paths and os.path.isdir(self.file_driver.environment_directory):
            paths.extend([
                os.path.join(self.file_driver.environment_directory, filepath)
                for filepath in list_all_filepaths(
                    self.file_driver.environment_directory)
            ])

        # c. add in default environment definition filepath as specified by the environment driver
        # if path exists and NO OTHER PATHS exist
        src_environment_filename = self.environment_driver.get_default_definition_filename(
        )
        src_environment_filepath = os.path.join(self.home,
                                                src_environment_filename)
        _, environment_filename = os.path.split(src_environment_filepath)
        create_dict['definition_filename'] = environment_filename
        if not paths and os.path.exists(src_environment_filepath):
            paths.append(src_environment_filepath)

        # Step 2: Check existing paths and create files as needed to populate the
        # full environment within the temporary directory

        paths = self._setup_compatible_environment(
            create_dict,
            paths,
            _temp_env_dir,
            save_hardware_file=save_hardware_file)

        # Step 3: Pass in all paths for the environment to the file collection create
        # If PathDoesNotExist is found for any source paths, then error
        if not paths:
            raise EnvironmentDoesNotExist()
        try:
            file_collection_obj = self.file_collection.create(paths)
        except PathDoesNotExist as e:
            raise PathDoesNotExist(
                __("error", "controller.environment.create.filepath.dne",
                   str(e)))

        # Step 4: Add file collection information to create dict and check unique hash
        create_dict['file_collection_id'] = file_collection_obj.id
        create_dict['unique_hash'] = file_collection_obj.filehash
        # Check if unique hash is unique or not.
        # If not, DO NOT CREATE Environment and return existing Environment object
        results = self.dal.environment.query(
            {"unique_hash": file_collection_obj.filehash})
        if results: return results[0]

        # Step 5: Delete the temporary directory
        shutil.rmtree(_temp_env_dir)

        # Step 6: Add optional arguments to the Environment entity
        for optional_arg in ["name", "description"]:
            if optional_arg in dictionary:
                create_dict[optional_arg] = dictionary[optional_arg]

        # Step 7: Create environment and return
        return self.dal.environment.create(Environment(create_dict))
Esempio n. 11
0
    def checkout(self, environment_id):
        """Checkout to specific environment id

        Parameters
        ----------
        environment_id : str
            environment id to checkout to

        Returns
        -------
        bool
            True if success

        Raises
        ------
        EnvironmentNotInitialized
            error if not initialized (must initialize first)
        PathDoesNotExist
            if environment id does not exist
        UnstagedChanges
            error if not there exists unstaged changes in environment

        """
        if not self.is_initialized:
            raise EnvironmentNotInitialized()
        if not self.exists(environment_id):
            raise EnvironmentDoesNotExist(
                __("error", "controller.environment.checkout_env",
                   environment_id))
        # Check if unstaged changes exist
        if self._has_unstaged_changes():
            raise UnstagedChanges()
        # Check if environment has is same as current
        results = self.dal.environment.query({"id": environment_id})
        environment_obj = results[0]
        environment_hash = environment_obj.unique_hash

        if self._calculate_project_environment_hash() == environment_hash:
            return True
        # Remove all content from project environment directory
        for file in os.listdir(self.file_driver.environment_directory):
            file_path = os.path.join(self.file_driver.environment_directory,
                                     file)
            try:
                if os.path.isfile(file_path):
                    os.remove(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except Exception as e:
                print(e)
        # Add in files for that environment id
        file_collection_obj = self.dal.file_collection.\
            get_by_id(environment_obj.file_collection_id)
        environment_definition_path = os.path.join(self.home,
                                                   file_collection_obj.path)
        # Copy to temp folder and remove files that are datmo specific
        _temp_env_dir = get_datmo_temp_path(self.home)
        self.file_driver.copytree(environment_definition_path, _temp_env_dir)
        for filename in self.environment_driver.get_datmo_definition_filenames(
        ):
            os.remove(os.path.join(_temp_env_dir, filename))
        # Copy from temp folder to project environment directory
        self.file_driver.copytree(_temp_env_dir,
                                  self.file_driver.environment_directory)
        shutil.rmtree(_temp_env_dir)
        return True