]> git.apps.os.sepia.ceph.com Git - teuthology.git/commitdiff
orchestra.remote: add move_file, copy_file and read_file 1538/head
authorKyr Shatskyy <kyrylo.shatskyy@suse.com>
Mon, 20 Jul 2020 13:16:32 +0000 (15:16 +0200)
committerKyr Shatskyy <kyrylo.shatskyy@suse.com>
Fri, 4 Sep 2020 13:25:42 +0000 (15:25 +0200)
Signed-off-by: Kyr Shatskyy <kyrylo.shatskyy@suse.com>
teuthology/misc.py
teuthology/orchestra/remote.py

index b66e78c0ca7cac6143e7572a6c0cd42132b47dd6..547709fd642c5121cd4112bf5421406e629a08e2 100644 (file)
@@ -624,7 +624,7 @@ def remove_lines_from_file(remote, path, line_is_valid_test,
     on when the main site goes up and down.
     """
     # read in the specified file
-    in_data = get_file(remote, path, False).decode()
+    in_data = remote.read_file(path, False).decode()
     out_data = ""
 
     first_line = True
@@ -667,17 +667,9 @@ def prepend_lines_to_file(remote, path, lines, sudo=False):
     """
 
     temp_file_path = remote.mktemp()
-
-    data = get_file(remote, path, sudo).decode()
-
-    # add the additional data and write it back out, using a temp file
-    # in case of connectivity of loss, and then mv it to the
-    # actual desired location
-    data = lines + data
-    write_file(remote, temp_file_path, data)
-
-    # then do a 'mv' to the actual file location
-    move_file(remote, temp_file_path, path, sudo)
+    remote.write_file(temp_file_path, lines)
+    remote.copy_file(path, temp_file_path, append=True, sudo=sudo)
+    remote.move_file(temp_file_path, path, sudo=sudo)
 
 
 def create_file(remote, path, data="", permissions=str(644), sudo=False):
@@ -773,7 +765,7 @@ def get_scratch_devices(remote):
     """
     devs = []
     try:
-        file_data = get_file(remote, "/scratch_devs").decode()
+        file_data = remote.read_file("/scratch_devs").decode()
         devs = file_data.split()
     except Exception:
         devs = remote.sh('ls /dev/[sv]d?').strip().split('\n')
index 2dbfbdd483459419b6805f41497ce808c8f6d7ad..84d39862d6d2b05a9f719145625e217f410dc729 100644 (file)
@@ -458,6 +458,94 @@ class Remote(object):
             ])
         return self.run(args=args, wait=False, stdout=run.PIPE)
 
+    def copy_file(self, src, dst, sudo=False, mode=None, owner=None,
+                                              mkdir=False, append=False):
+        """
+        Copy data to remote file
+
+        :param src:     source file path on remote host
+        :param dst:     destination file path on remote host
+        :param sudo:    use sudo to write file, defaults False
+        :param mode:    set file mode bits if provided
+        :param owner:   set file owner if provided
+        :param mkdir:   ensure the destination directory exists, defaults False
+        :param append:  append data to the file, defaults False
+        """
+        dd = 'sudo dd' if sudo else 'dd'
+        args = dd + ' if=' + src + ' of=' + dst
+        if append:
+            args += ' conv=notrunc oflag=append'
+        if mkdir:
+            mkdirp = 'sudo mkdir -p' if sudo else 'mkdir -p'
+            dirpath = os.path.dirname(dst)
+            if dirpath:
+                args = mkdirp + ' ' + dirpath + '\n' + args
+        if mode:
+            chmod = 'sudo chmod' if sudo else 'chmod'
+            args += '\n' + chmod + ' ' + mode + ' ' + dst
+        if owner:
+            chown = 'sudo chown' if sudo else 'chown'
+            args += '\n' + chown + ' ' + owner + ' ' + dst
+        args = 'set -ex' + '\n' + args
+        self.run(args=args)
+
+    def move_file(self, src, dst, sudo=False, mode=None, owner=None,
+                                              mkdir=False):
+        """
+        Move data to remote file
+
+        :param src:     source file path on remote host
+        :param dst:     destination file path on remote host
+        :param sudo:    use sudo to write file, defaults False
+        :param mode:    set file mode bits if provided
+        :param owner:   set file owner if provided
+        :param mkdir:   ensure the destination directory exists, defaults False
+        """
+        mv = 'sudo mv' if sudo else 'mv'
+        args = mv + ' ' + src + ' ' + dst
+        if mkdir:
+            mkdirp = 'sudo mkdir -p' if sudo else 'mkdir -p'
+            dirpath = os.path.dirname(dst)
+            if dirpath:
+                args = mkdirp + ' ' + dirpath + '\n' + args
+        if mode:
+            chmod = 'sudo chmod' if sudo else 'chmod'
+            args += ' && ' + chmod + ' ' + mode + ' ' + dst
+        if owner:
+            chown = 'sudo chown' if sudo else 'chown'
+            args += ' && ' + chown + ' ' + owner + ' ' + dst
+        self.run(args=args)
+
+    def read_file(self, path, sudo=False, stdout=None,
+                              offset=0, length=0):
+        """
+        Read data from remote file
+
+        :param path:    file path on remote host
+        :param sudo:    use sudo to read the file, defaults False
+        :param stdout:  output object, defaults to io.BytesIO()
+        :param offset:  number of bytes to skip from the file
+        :param length:  number of bytes to read from the file
+        """
+        dd = 'sudo dd' if sudo else 'dd'
+        args = dd + ' if=' + path + ' of=/dev/stdout'
+        iflags=[]
+        # we have to set defaults here instead of the method's signature,
+        # because python is reusing the object from call to call
+        stdout = stdout or BytesIO()
+        if offset:
+            args += ' skip=' + str(offset)
+            iflags += 'skip_bytes'
+        if length:
+            args += ' count=' + str(length)
+            iflags += 'count_bytes'
+        if iflags:
+            args += ' iflag=' + ','.join(iflags)
+        args = 'set -ex' + '\n' + args
+        proc = self.run(args=args, stdout=stdout)
+        return proc.stdout.getvalue()
+
+
     def write_file(self, path, data, sudo=False, mode=None, owner=None,
                                      mkdir=False, append=False):
         """