def _move_music(self, remote_site): " List albums and move music " if remote_site not in self.connection_map: try: self.connection_map[remote_site] = ConnectionManager(remote_site, self.config["local_music"]) except (SSHException, socket.error), err: Message.err("Failed to connect: %s" % (err)) return
def _copy_dir(self, remote_dir, dest): " copy a directory to local " if self.recurse_count >= self.max_recurse: return try: # mkdir on local os.mkdir(dest) except OSError, err: Message.err("Failed to create dir %s: %s" % (dest, err)) return
def pull_album(self, path, file): " Pull an album over the local using sftp " target = path + file dest = self.local_music.get_save_dir().rstrip("/") + "/" + file # Check if target is a directory try: if S_ISDIR(self.scp_client.stat(target).st_mode): self._copy_dir(target, dest) else: # copy single file self.scp_client.get(target, dest) except (IOError, OSError), err: Message.err("Failed to move file %s: %s" % (file, err))
def load(self): " Load the config " # attempt load try: f_config = open(self.serial_config_file) config = jsonpickle.decode(f_config.read()) self.update(config) f_config.close() except (IOError, ValueError): Message.err("No serialized config found, or error reading config.") return self["local_music"].refresh_album_cache() Message.note("Album cache refreshed")
def connect(self): " connect to the host " # ssh ssh_client = paramiko.SSHClient() ssh_client.load_system_host_keys() try: ssh_client.connect( self.remote_site.hostname, self.remote_site.port, self.remote_site.username, self.password ) except SSHException, err: if self.password: raise SSHException("Password authentication failed: %s" % (err)) Message.err("Connect failed: %s" % (err)) self.password = Input.prompt_pass() self.connect()
def _music_sites(self): " List, Remove, Update music sites " if len(self.config["local_music"].get_dir_list()) < 1: Message.err("You must have at least one local dir to move music.") return False while True: action, index = Menu.display_sites(self.config["sites"]) if action == "q": return if action == "n": code, data = Input.site_data() if not code: continue site = RemoteSite(data["name"], data["username"], data["hostname"], data["port"]) self.config["sites"].append(site) continue # existing site actions if index < 1: Message.err("You must specify a site to perform the action on.") continue index -= 1 remote_site = self.config["sites"][index] if action == "d": if Input.confirm_delete(): self.config["sites"].pop(index) elif action == "l": self._remote_dirs(remote_site) elif action == "b": self._remote_blocks(remote_site) elif action == "m": if len(remote_site.get_dir_list()) < 1: Message.err("Remote sites must have at least 1 dir to move music.") continue self._move_music(remote_site)
def cleanup(self): self.config.save() Message.note("Done.")
try: # loop through all files for sub_file in self.scp_client.listdir(path=remote_dir): path_sub_file = "%s/%s" % (remote_dir, sub_file) if S_ISDIR(self.scp_client.stat(path_sub_file).st_mode): # recurse into directories self.recurse_count += 1 self._copy_dir(path_sub_file, "%s/%s" % (dest, sub_file)) self.recurse_count -= 1 continue # copy the file then self.scp_client.get(path_sub_file, "%s/%s" % (dest, sub_file)) except (IOError, OSError), err: Message.err("Failed to move file(s) %s: %s" % (sub_file, err)) def _parse_album_list(self, stdout): " Parse the directory listing into a map " active_dir = self.remote_site.get_dir_list()[0] album_map = {} for line in stdout: line = line.rstrip() if len(line) < 1: continue if self.dir_pattern.match(line): active_dir = line.rstrip(":") continue album_map[line] = active_dir return album_map