def download_file(self, remote, local): """Downloads remote files to local path. :param remote: (str) Remote path. :param local: (str) Local path. :return: (bool) True on success, False on failure. """ if not self.isfile_remote(remote): return self.err(1, remote) if not hasstring(local): return self.err(2, local) if isdir(local) and local[-1] != '/': local += '/' if local[-1] == '/': local += remote.split('/')[:-1] if not isdir('/'.join(local.split('/')[:-1]), True): return self.err(3, local) try: self.connection.get(remote, local) return True except Exception: _, message = getexcept() return self.err(4, message)
def mkdir_remote(self, data): """Creates remote directories. :param data: (str) Path. :return: (bool) True on success, False on failure. """ if not hasstring(data): return False if data[-1] == '/': data = data[:-1] path = data.split('/') path_c = len(path) index = 1 for index in range(0, path_c): try: if stat.S_ISREG( self.connection.stat( '/'.join(path[0:index + 1])).st_mode): return False except IOError: index -= 1 break if index < path_c - 1: try: for index in range(index + 1, path_c): self.connection.mkdir('/'.join(path[0:index + 1])) except IOError: _, message = getexcept() return self.err(1, message) return True
def upload_file(self, local, remote): """Uploads local files to remote host. :param local: (str) Local path. :param remote: (str) Remote path. :return: (bool) True on success, False on failure. """ if not isfile(local): return self.err(1, local) if not hasstring(remote): return self.err(2, remote) if self.isdir_remote(remote) and remote[-1] != '/': remote += '/' if remote[-1] == '/': remote += local.split('/')[-1] if not self.isdir_remote('/'.join(remote.split('/')[:-1]), True): return self.err(3, remote) try: self.connection.put(local, remote) return True except Exception: _, message = getexcept() return self.err(4, message)
def csv_parse(lines): """Converts the CSV-expected input to array. :param lines: (str / [str]) CSV input - it can either linefeeded string or list. :return: ([str]) String Array or None on error. """ if not lines: return None if not haslist(lines): if hasstring(lines): lines = lines.split('\n') else: return None try: return list(csv.reader(lines, delimiter=',', quotechar='"')) except Exception: getexcept() return None
def isport(data): """TCP/UDP Port validation. :param data: (int / long) Port. :return: (bool) True or False. """ if not isinstance(data, (int, long)): try: data = int(data) except Exception: return getexcept() if data < 1 or data > 65536: return False return True
def isdir(data, makedirs=False): """Directory validation and auto-creation. :param data: (str) Directory. :return: (bool) True or False. """ if not hasstring(data): return False if makedirs: if not os.path.isdir(data): try: os.makedirs(data) except Exception: return getexcept() return os.path.isdir(data)
def upload_dir(self, local, remote): """Uploads local directories to remote host. Source: https://www.tutorialspoint.com/python/os_walk.htm :param local: (str) Local path. :param remote: (str) Remote path. :return: (bool) True on success, False on failure. """ if not isdir(local): return self.err(1, local) if self.isfile_remote(remote): return self.err(2, remote) if not self.isdir_remote(remote, True): return self.err(3, remote) if local[-1] == '/': local = local[:-1] if remote[-1] == '/': remote = remote[:-1] local_c = len(local) for root, dirs, files in os.walk(local, topdown=False): remote_root = remote + root[local_c:] if not self.mkdir_remote(remote_root): return self.err(4, remote_root) for name in dirs: remote_dir = remote_root + '/' + name if not self.mkdir_remote(remote_dir): return self.err(5, remote_dir) try: for name in files: remote_file = remote_root + '/' + name self.connection.put(root + '/' + name, remote_file) except Exception: _, message = getexcept() self.err(6, remote_file) return self.err(7, message) return True
def disconnect(self): """Disconnects from current host, unless it is already disconnected. :return: (bool) True on success, False on failure. """ if not self.checkconnection(): return True try: self.connection.close() self.status = 0 return True except Exception: _, message = getexcept() return self.err(1, message)
def download_dir(self, remote, local): """Downloads remote directories to local path. :param remote: (str) Remote path. :param local: (str) Local path. :return: (bool) True on success, False on failure. """ if not self.isdir_remote(remote): return self.err(1, remote) if isfile(local): return self.err(2, local) if not isdir(local, True): return self.err(3, local) if remote[-1] == '/': remote = remote[:-1] if local[-1] == '/': local = local[:-1] remote_c = len(remote) for root, dirs, files in self.walk_remote(remote): local_root = local + root[remote_c:] if not isdir(local_root, True): return self.err(4, local_root) for name in dirs: local_dir = local_root + '/' + name if not isdir(local_dir, True): return self.err(5, local_dir) try: for name in files: local_file = local_root + '/' + name self.connection.get(root + '/' + name, local_file) except Exception: _, message = getexcept() self.err(6, local_file) return self.err(7, message) return True
def checkconnection(self): """Sends a single null command to check the connectivity. :return: (bool) True on success, False on failure. """ try: transport = self.connection.get_transport() transport.send_ignore() self.status = 1 return True except (EOFError, AttributeError): self.status = 0 return False except Exception: _, message = getexcept() return self.err(1, message)
def writejson(filename, data): """Saves the (dict) data to JSON file. :param filename: (str) Filename to write JSON to. :param data: (dict) Dict to save to JSON file. :return: (bool) True on success, False on failure. """ if not hasstring(filename): return False if not isdir('/'.join(filename.split('/')[:-1]), True): return False if not isinstance(data, dict): return False try: with open(filename, 'w') as handler: json.dump(data, handler) except IOError: return getexcept() return True
def writefile(filename, lines): """Saves lines to file. :param filename: (str) File to write. :param lines: (list) List of lines to write. :return: (bool) True on success, False on failure. """ if not isdir('/'.join(filename.split('/')[:-1]), True): return False if not haslist(lines): return False try: handler = open(filename, 'w') for line in lines: handler.write(line + '\n') handler.close() return True except Exception: return getexcept() return False
def connect(self, timeout=30): """Connects to remote host via SFTP. :param timeout: (int) Connection timeout. :return: (bool) Connection status. """ if not isinstance(timeout, int) or timeout < 0: timeout = 30 if self.status < 0: return self.err(1, self.status) if self.status == 1: if self.checkconnection(): return True # Check this approach (timeout is not being used): # https://stackoverflow.com/questions/9758432/timeout-in-paramiko-python _ = timeout # After changing it, in the password connect, add: # allow_agent=False, look_for_keys=False try: if self.pkey_string: handler = StringIO.StringIO(self.pkey_string) self.pkey = paramiko.RSAKey.from_private_key(handler) handler.close() elif self.pkey_file: self.pkey = paramiko.RSAKey.from_private_key_file( self.pkey_file) self.transport = paramiko.Transport((self.host, self.port)) if self.pkey: self.ssh_auth = 2 self.transport.connect(username=self.username, pkey=self.pkey) else: self.ssh_auth = 1 self.transport.connect(username=self.username, password=self.password) self.connection = paramiko.SFTPClient.from_transport( self.transport) self.status = 1 return True except socket.error: _, message = getexcept() err_code = 2 except paramiko.AuthenticationException: _, message = getexcept() err_code = 3 except paramiko.BadHostKeyException: _, message = getexcept() err_code = 4 except paramiko.SSHException: _, message = getexcept() err_code = 5 except Exception: _, message = getexcept() err_code = 6 return self.err(err_code, message)
def connect(self, timeout=30): """Connects to remote host via SSH. :param timeout: (int) Connection timeout. :return: (bool) Connection status. """ if not isinstance(timeout, int) or timeout < 0: timeout = 30 if self.status < 0: return self.err(1, self.status) if self.status == 1: if self.checkconnection(): return True try: if self.pkey_string: handler = StringIO.StringIO(self.pkey_string) self.pkey = paramiko.RSAKey.from_private_key(handler) handler.close() elif self.pkey_file: self.pkey = paramiko.RSAKey.from_private_key_file( self.pkey_file) self.connection = paramiko.SSHClient() self.connection.set_missing_host_key_policy( paramiko.AutoAddPolicy()) if self.pkey: self.ssh_auth = 2 self.connection.connect(hostname=self.host, port=self.port, username=self.username, pkey=self.pkey, timeout=timeout) else: self.ssh_auth = 1 self.connection.connect(hostname=self.host, port=self.port, username=self.username, password=self.password, timeout=timeout, allow_agent=False, look_for_keys=False) self.status = 1 return True except socket.error: _, message = getexcept() err_code = 2 except paramiko.AuthenticationException: _, message = getexcept() err_code = 3 except paramiko.BadHostKeyException: _, message = getexcept() err_code = 4 except paramiko.SSHException: _, message = getexcept() err_code = 5 except Exception: _, message = getexcept() err_code = 6 return self.err(err_code, message)
def command(self, command, raw=False, connect=True, hasstdout=True): """Executes the <command> on the remote host and returns the results. :param command: (str) The command that has to be executed. :param raw: (bool) Returns all results without filtering lines that start with #. :param connect: (bool) Connects to host, if it is not connected already. :param hasstdout: (bool) Is it expected the command to give output? :return: (list) The execution result. """ status = 0 self.history.append(command) if not hasstring(command): self.err(1) return None if self.status < 1 and connect: if self.connect(): status = 1 if self.status < 1: self.err(2, self.status) return None if self.reseterrors: self.err0() lines = [] try: # stdin, stdout, stderr = ... _, stdout, stderr = self.connection.exec_command(command) lines = stdout.read().replace('\r', '').split('\n') # Mikrotik CLI is not producing stderr. Linux does. if not (hasstring(lines) or haslist(lines)): lines = stderr.read().replace('\r', '').split('\n') except Exception: _, message = getexcept() self.err(3, message) finally: if status == 1: self.disconnect() ##### fix the logic ^^^ \/\/\/\ of get/except/disconnect results = [] if raw: for line in lines: results.append(line) elif lines: for line in lines: if line: if line[0] != '#': results.append(line.strip()) if not haslist(results) and hasstdout: self.err(4, command) return results