def disconnect(self) -> None:
     # ADD DOCSTRING
     if not self.connected:
         raise SSHConnectionError(
             'Not currently connected to a remote host')
     self.shell.close()
     self.connected = False
     self.port = None
 def connect(self,
             hostname: Optional[str] = None,
             username: Optional[str] = None,
             password: Optional[str] = None,
             use_key: bool = False,
             login: bool = False,
             port: Optional[int] = None,
             timeout: int = 60,
             retries: int = 0,
             retry_delay: int = 1) -> None:
     # ADD DOCSTRING
     # TODO: deal with prompting for required fields if not provided
     if self.connected:
         raise SSHConnectionError(
             'already connected to a remote host. use `SshShell.disconnect` '
             'to disconnect from the current host before connecting to a new '
             'one, or `SshShell.reconnect` to reset the connection to the '
             'current host')
     port = port or self.port or 22
     hostname = hostname or self.hostname or input("Hostname: ")
     username = username or self.username or input("Username: "******"Password: ")
     self._shell = spurplus.connect_with_retries(
         hostname=hostname,
         username=username,
         password=password,
         look_for_private_keys=(not use_key),
         port=port,
         connect_timeout=timeout,
         retries=retries,
         retry_period=retry_delay)
     # only update attrs if connection is successful
     self.hostname = hostname
     self.username = username
     self.port = port
     self.connected = True
     if self._environ is None:
         # read environment variables
         tmp_exe = self.executable or '/bin/bash'
         if login:
             printenv_command = [tmp_exe, '-lc', 'printenv']
         else:
             printenv_command = ['printenv']
         # TODO: a more robust solution for this in case BASH_FUNC_module isn't last
         initial_env = self.shell.check_output(printenv_command).split(
             '\nBASH_FUNC_module()')[0]
         initial_env = dict(
             map(lambda x: x.split('=', maxsplit=1),
                 initial_env.splitlines()))
         self._environ = PseudoEnviron(initial_env=initial_env,
                                       custom_vars=self._env_additions)
     # initial validation of properties that depend on environment
     self.cwd = self._cwd
     self.executable = self._executable
示例#3
0
 def remote_path(self, path: PathLike):
     if self._remote_path is not None:
         raise AttributeError(
             "local/remote path mapping is read-only once set")
     elif not self._cluster.connected:
         raise SSHConnectionError(
             "Connection to remote host must be open to assign a remote "
             "path to a file mapping")
     path = self._cluster.resolve_path(PurePosixPath(path), strict=False)
     self._remote_path = path
     self._init_remote()
示例#4
0
 def load_project(self, name: str):
     # ADD DOCSTRING
     # loads a project form $HOME/.clustertools
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to load a project")
     elif self.project is not None:
         raise ClusterToolsProjectError(
             f"Project '{self.project.name}' is already loaded. Use "
             "'cluster.unload_project()' to unload the current project "
             "before loading a new one")
     self.project = Project.load(name=name, cluster=self)
     self._mixin_project()
示例#5
0
 def create_project(self, name: str, **kwargs):
     # ADD DOCSTRING - creates a new project configuration & an entry
     #  in $HOME/.clustertools
     # TODO: should take all (or most) arguments in Project constructor
     # TODO: would be possible to allow creating/partially loading
     #  projects before connecting, but would require a lot of
     #  additional coding around possible scenarios
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to create a project")
     elif self.project is not None:
         raise ClusterToolsProjectError(
             "Cannot create a project when one is already loaded. Use "
             "'cluster.unload_project()' to unload the current project "
             "before creating a new one.")
     elif name in self.all_projects:
         raise ClusterToolsProjectError(
             f"Project '{name}' already exists. Use "
             f"cluster.load_project('{name}') to load its previous state.")
     self.project = Project(name=name, cluster=self, **kwargs)
     self._all_projects = tuple(
         list(self._all_projects) + [self.project.name])
     self._mixin_project()
 def executable(self) -> str:
     # ADD DOCSTRING
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to determine remote shell")
     return self._executable
 def environ(self) -> PseudoEnviron:
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to access remote environment")
     return self._environ
 def cwd(self: BaseShell) -> PurePosixPath:
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to access remote file system")
     return self._cwd
 def shell(self) -> spurplus.SshShell:
     if not self.connected:
         raise SSHConnectionError(
             "SSH connection must be open to access remote shell")
     return self._shell