def stop(self, **kwargs): task_id = kwargs.get('id', None) self.cli_helper.echo(__("info", "cli.task.stop", task_id)) try: result = self.task_controller.stop(task_id) if not result: self.cli_helper.echo(__("error", "cli.task.stop", task_id)) return result except: self.cli_helper.echo(__("error", "cli.task.stop", task_id)) return False
def init(self): try: # Ensure the Datmo file structure exists self.ensure_datmo_file_structure() except Exception as e: raise FileIOException( __("error", "controller.file.driver.local.init", str(e))) return True
def reset(self, git_commit): try: subprocess.check_output([self.execpath, "reset", git_commit], cwd=self.filepath).strip() except Exception as e: raise GitExecutionException( __("error", "controller.code.driver.git.reset", str(e))) return True
def list_file_collections(self): if not self.is_initialized: raise FileStructureError( __("error", "controller.file.driver.local.list_file_collections")) collections_path = os.path.join(self.datmo_directory, "collections") collections_list = os.listdir(collections_path) return collections_list
def wrapper(self, *args, **kwargs): controller_obj = controller_class() if controller_obj.environment_driver.type == "docker": if check_docker_inactive(controller_obj.home): Helper.echo( __("error", "general.environment.docker.na")) return return function(self, *args, **kwargs)
def push_ref(self, commit_id="*"): datmo_ref = "refs/datmo/" + commit_id datmo_ref_map = "+" + datmo_ref + ":" + datmo_ref try: return self.push("origin", name=datmo_ref_map) except Exception as e: raise GitExecutionException( __("error", "controller.code.driver.git.push_ref", str(e)))
def create_environment_dir(self): if not os.path.isdir(self._datmo_directory_path): raise FileStructureError( __("error", "controller.file.driver.local.create_collections_dir")) if not os.path.isdir(self.environment_directory_path): os.makedirs(self.environment_directory_path) return True
def delete(self, **kwargs): self.task_controller = TaskController() task_id = kwargs.get("id", None) if task_id: self.cli_helper.echo(__("info", "cli.run.delete", task_id)) else: raise RequiredArgumentMissing() try: # Delete the task for the run result = self.task_controller.delete(task_id) if result: self.cli_helper.echo( __("info", "cli.run.delete.success", task_id)) return result except Exception: self.cli_helper.echo(__("error", "cli.run.delete", task_id)) return False
def current_session(self): if not self.model: raise DatmoModelNotInitialized( __("error", "controller.base.current_session")) if self._current_session == None: sessions = self.dal.session.query({"current": True}) self._current_session = sessions[0] if sessions else None return self._current_session
def __init__(self): super(SnapshotController, self).__init__() self.code = CodeController() self.file_collection = FileCollectionController() self.environment = EnvironmentController() if not self.is_initialized: raise ProjectNotInitialized( __("error", "controller.snapshot.__init__"))
def exists_datmo_files_in_worktree(self): try: process = subprocess.Popen( [self.execpath, "ls-files", "|", "grep", ".datmo"], cwd=self.filepath, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode > 0: raise GitExecutionError( __("error", "controller.code.driver.git.init", str(stderr))) result = stdout.decode().strip() return True if result else False except subprocess.CalledProcessError as e: raise GitExecutionError( __("error", "controller.code.driver.git.init", str(e)))
def reset(self, git_commit): try: process = subprocess.Popen( [self.execpath, "reset", git_commit], cwd=self.filepath, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() _ = stdout.decode().strip() if process.returncode > 0: raise GitExecutionError( __("error", "controller.code.driver.git.reset", str(stderr))) except subprocess.CalledProcessError as e: raise GitExecutionError( __("error", "controller.code.driver.git.reset", str(e))) return True
def checkout(self, **kwargs): self.snapshot_controller = SnapshotController() snapshot_id = kwargs.get('id') checkout_success = self.snapshot_controller.checkout(snapshot_id) if checkout_success: self.cli_helper.echo( __("info", "cli.snapshot.checkout.success", snapshot_id)) return self.snapshot_controller.checkout(snapshot_id)
def rerun(self, **kwargs): self.task_controller = TaskController() # Get task id task_id = kwargs.get("id", None) self.cli_helper.echo(__("info", "cli.run.rerun", task_id)) # Create the task_obj task_obj = self.task_controller.get(task_id) # Create the run obj run_obj = RunObject(task_obj) # Select the initial snapshot if it's a script else the final snapshot initial = True if run_obj.type == 'script' else False environment_id = run_obj.environment_id command = task_obj.command_list snapshot_id = run_obj.core_snapshot_id if not initial else run_obj.before_snapshot_id # Checkout to the core snapshot id before rerunning the task self.snapshot_controller = SnapshotController() try: checkout_success = self.snapshot_controller.checkout(snapshot_id) except Exception: self.cli_helper.echo(__("error", "cli.snapshot.checkout.failure")) sys.exit(1) if checkout_success: self.cli_helper.echo( __("info", "cli.snapshot.checkout.success", snapshot_id)) # Rerunning the task # Create input dictionary for the new task snapshot_dict = {} snapshot_dict["environment_id"] = environment_id task_dict = { "ports": task_obj.ports, "interactive": task_obj.interactive, "mem_limit": task_obj.mem_limit, "command_list": command } # Run task and return Task object result new_task_obj = self.task_run_helper(task_dict, snapshot_dict, "cli.run.run") if not new_task_obj: return False # Creating the run object new_run_obj = RunObject(new_task_obj) return new_run_obj
def exists_datmo_files_in_worktree(self): try: result = subprocess.check_output( [self.execpath, "ls-files", "|", "grep", ".datmo"], cwd=self.filepath).strip() return True if result else False except Exception as e: raise GitExecutionException( __("error", "controller.code.driver.git.init", str(e)))
def init(self): try: # Ensure the environment files structure exists self.ensure_environment_dir() except Exception as e: raise EnvironmentInitFailed( __("error", "controller.environment.driver.docker.init", str(e))) return True
def __init__(self): super(TaskController, self).__init__() self.environment = EnvironmentController() self.snapshot = SnapshotController() self.spinner = Spinner() if not self.is_initialized: raise ProjectNotInitialized( __("error", "controller.task.__init__"))
def create_files_dir(self): if not self.exists_hidden_datmo_dir(): raise FileStructureError( __("error", "controller.file.driver.local.create_collections_dir")) relative_files_path = os.path.join(self.datmo_directory_name, "files") if not self.exists(relative_files_path, directory=True): self.create(relative_files_path, directory=True) return True
def wrapper(self, *args, **kwargs): controller_obj = controller_class() if controller_obj.environment_driver.type == "docker": # TODO: abstract the datmo_directory_name if check_docker_inactive(controller_obj.home, ".datmo"): Helper.echo( __("error", "general.environment.docker.na")) return return function(self, *args, **kwargs)
def create_collections_dir(self): if not self.is_initialized: raise FileStructureException( __("error", "controller.file.driver.local.create_collections_dir")) collections_path = os.path.join(self.filepath, ".datmo", "collections") if not os.path.isdir(collections_path): os.makedirs(collections_path) return True
def __init__(self, filepath): super(LocalFileDriver, self).__init__() self.filepath = filepath # Check if filepath exists if not os.path.exists(self.filepath): raise PathDoesNotExist( __("error", "controller.file.driver.local.__init__", filepath)) self._is_initialized = self.is_initialized self.type = "local"
def connect(self): # TODO: Fill in to start up Docker # Startup Docker try: pass except Exception as e: raise EnvironmentExecutionError( __("error", "controller.environment.driver.docker.init", str(e))) # Initiate Docker execution try: self.info = self.client.info() self._is_connected = True if self.info["Images"] != None else False except Exception: raise EnvironmentConnectFailed( __("error", "controller.environment.driver.docker.__init__", platform.system())) return True
def latest_commit(self): try: process = subprocess.Popen( [self.execpath, "log", "--format=%H", "-n", "1"], cwd=self.filepath, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode > 0: raise GitExecutionError( __("error", "controller.code.driver.git.latest_commit", str(stderr))) git_commit = stdout.decode().strip() except subprocess.CalledProcessError as e: raise GitExecutionError( __("error", "controller.code.driver.git.latest_commit", str(e))) return git_commit
def delete_ref(self, commit_id): self.ensure_code_refs_dir() code_ref_path = os.path.join(self.filepath, ".git/refs/datmo/", commit_id) if not self.exists_ref(commit_id): raise FileIOError( __("error", "controller.code.driver.git.delete_ref")) os.remove(code_ref_path) return True
def run(self, **kwargs): self.task_controller = TaskController() self.cli_helper.echo(__("info", "cli.task.run")) # Create input dictionaries snapshot_dict = {} # Environment if kwargs.get("environment_id", None) or kwargs.get( "environment_paths", None): mutually_exclusive_args = ["environment_id", "environment_paths"] mutually_exclusive(mutually_exclusive_args, kwargs, snapshot_dict) task_dict = { "ports": kwargs['ports'], "interactive": kwargs['interactive'], "mem_limit": kwargs['mem_limit'] } if not isinstance(kwargs['cmd'], list): if platform.system() == "Windows": task_dict['command'] = kwargs['cmd'] elif isinstance(kwargs['cmd'], basestring): task_dict['command_list'] = shlex.split(kwargs['cmd']) else: task_dict['command_list'] = kwargs['cmd'] # Create the task object task_obj = self.task_controller.create() updated_task_obj = task_obj try: # Pass in the task updated_task_obj = self.task_controller.run( task_obj.id, snapshot_dict=snapshot_dict, task_dict=task_dict) except Exception as e: self.logger.error("%s %s" % (e, task_dict)) self.cli_helper.echo("%s" % e) self.cli_helper.echo(__("error", "cli.task.run", task_obj.id)) return False finally: self.cli_helper.echo(__("info", "cli.task.run.stop")) self.task_controller.stop(updated_task_obj.id) self.cli_helper.echo( __("info", "cli.task.run.complete", updated_task_obj.id)) return updated_task_obj
def setup(self, **kwargs): self.environment_controller = EnvironmentController() environment_type = kwargs.get("type", None) environment_framework = kwargs.get("framework", None) environment_language = kwargs.get("language", None) # TODO: remove business logic from here and create common helper # environment types environment_types = self.environment_controller.get_environment_types() if not environment_type or environment_type not in environment_types: environment_type = self.cli_helper.prompt_available_options( environment_types, option_type="type") # environment frameworks available_framework_details = self.environment_controller.get_supported_frameworks( environment_type) available_frameworks = [ item[0] for item in available_framework_details ] if not environment_framework or environment_framework not in available_frameworks: environment_framework = self.cli_helper.prompt_available_options( available_framework_details, option_type="framework") # environment languages available_environment_languages = self.environment_controller.get_supported_languages( environment_type, environment_framework) if available_environment_languages and not environment_language or environment_language not in available_environment_languages: environment_language = self.cli_helper.prompt_available_options( available_environment_languages, option_type="language") try: options = { "environment_type": environment_type, "environment_framework": environment_framework, "environment_language": environment_language } environment_obj = self.environment_controller.setup( options=options) self.cli_helper.echo( __("info", "cli.environment.setup.success", (environment_obj.name, environment_obj.id))) return environment_obj except EnvironmentDoesNotExist: self.cli_helper.echo( __( "error", "cli.environment.setup.argument", "%s:%s-%s" % (environment_framework, environment_type, environment_language)))
def create_requirements_file(self, package_manager="pip"): """Create python requirements txt file for the project Parameters ---------- package_manager : str, optional the package manager being used during the snapshot creation Returns ------- str absolute filepath for requirements file Raises ------ EnvironmentRequirementsCreateError error in running package manager command to extract environment requirements """ if package_manager == "pip": try: requirements_filepath = os.path.join(self.root, "datmorequirements.txt") outfile_requirements = open(requirements_filepath, "wb") process = subprocess.Popen(["pip", "freeze"], cwd=self.root, stdout=outfile_requirements, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode > 0: raise EnvironmentRequirementsCreateError( __("error", "controller.environment.requirements.create", str(stderr))) except Exception as e: raise EnvironmentRequirementsCreateError( __("error", "controller.environment.requirements.create", str(e))) if not os.path.isfile(requirements_filepath): return None return requirements_filepath else: raise EnvironmentRequirementsCreateError( __("error", "controller.environment.requirements.create", "no such package manager"))
def create_ref(self, commit_id=None): """Add remaining files, make a commit and add it to a datmo code ref Parameters ---------- commit_id : str, optional if commit_id is given, it will not add files and not create a commit Returns ------- commit_id : str code id for the ref created Raises ------ GitCommitDoesNotExist commit id specified does not match a valid commit within the tree """ self.ensure_code_refs_dir() if not commit_id: # add files and commit changes on current branch self.add("-A") new_commit_bool = self.commit( options=["-m", "auto commit by datmo"]) try: commit_id = self.latest_commit() except GitExecutionException as e: raise GitCommitDoesNotExist( __("error", "controller.code.driver.git.create_ref.cannot_commit", str(e))) # revert back to the original commit if new_commit_bool: self.reset(commit_id) # writing git commit into ref if exists if not self.exists_commit(commit_id): raise GitCommitDoesNotExist( __("error", "controller.code.driver.git.create_ref.no_commit", commit_id)) code_ref_path = os.path.join(self.filepath, ".git/refs/datmo/", commit_id) with open(code_ref_path, "w") as f: f.write(to_unicode(commit_id)) return commit_id
def stop_remove_containers_by_term(self, term, force=False): """Stops and removes containers by term """ try: running_docker_container_cmd_list = list(self.cpu_prefix) running_docker_container_cmd_list.extend([ "ps", "-a", "|", "grep", "'", term, "'", "|", "awk '{print $1}'" ]) running_docker_container_cmd_str = str( " ".join(running_docker_container_cmd_list)) output = subprocess.Popen(running_docker_container_cmd_str, shell=True, stdout=subprocess.PIPE) out_list_cmd, err_list_cmd = output.communicate() # checking for running container id before stopping any if out_list_cmd: docker_container_stop_cmd_list = list(self.cpu_prefix) docker_container_stop_cmd_list = docker_container_stop_cmd_list + \ ["stop", "$("] + running_docker_container_cmd_list + \ [")"] docker_container_stop_cmd_str = str( " ".join(docker_container_stop_cmd_list)) output = subprocess.Popen(docker_container_stop_cmd_str, shell=True, stdout=subprocess.PIPE) _, _ = output.communicate() # rechecking for container id after stopping them to ensure no errors output = subprocess.Popen(running_docker_container_cmd_str, shell=True, stdout=subprocess.PIPE) out_list_cmd, _ = output.communicate() if out_list_cmd: docker_container_remove_cmd_list = list(self.cpu_prefix) if force: docker_container_remove_cmd_list = docker_container_remove_cmd_list + \ ["rm", "-f", "$("] + running_docker_container_cmd_list + \ [")"] else: docker_container_remove_cmd_list = docker_container_remove_cmd_list + \ ["rm", "$("] + running_docker_container_cmd_list + \ [")"] docker_container_remove_cmd_str = str( " ".join(docker_container_remove_cmd_list)) output = subprocess.Popen(docker_container_remove_cmd_str, shell=True, stdout=subprocess.PIPE) _, _ = output.communicate() except Exception as e: raise EnvironmentExecutionException( __( "error", "controller.environment.driver.docker.stop_remove_containers_by_term", str(e))) return True
def update(self, **kwargs): self.snapshot_controller = SnapshotController() self.cli_helper.echo(__("info", "cli.snapshot.update")) snapshot_id = kwargs.get('id') # getting previous saved config and stats snapshot_obj = self.snapshot_controller.get(snapshot_id) config = snapshot_obj.config stats = snapshot_obj.stats # extracting config update_config_list = kwargs.get('config', None) if update_config_list: update_config = {} for item in update_config_list: item_parsed_dict = parse_cli_key_value(item, 'config') update_config.update(item_parsed_dict) # updating config config.update(update_config) # extracting stats update_stats_list = kwargs.get('stats', None) if update_stats_list: update_stats = {} for item in update_stats_list: item_parsed_dict = parse_cli_key_value(item, 'stats') update_stats.update(item_parsed_dict) # updating stats stats.update(update_stats) # extracting message message = kwargs.get('message', None) # extracting label label = kwargs.get('label', None) result = self.snapshot_controller.update( snapshot_id, config=config, stats=stats, message=message, label=label) self.cli_helper.echo( __("info", "cli.snapshot.update.success", snapshot_id)) return result