Skip to content

Commit

Permalink
Support whitespace in subvol and paths managed by sync.btrfs* drvs
Browse files Browse the repository at this point in the history
  • Loading branch information
cvaroqui committed Mar 20, 2023
1 parent 4069669 commit 9caf967
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 29 deletions.
37 changes: 18 additions & 19 deletions opensvc/drivers/resource/sync/btrfs/__init__.py
@@ -1,8 +1,7 @@
import os
import time
import json

from subprocess import *
import subprocess

import core.status
import utilities.subsystems.btrfs
Expand Down Expand Up @@ -113,7 +112,7 @@ def sort_rset(self, rset):
def _info(self):
data = [
["src", self.src],
["target", " ".join(self.target) if self.target else ""],
["target", subprocess.list2cmdline(self.target) if self.target else ""],
]
data += self.stats_keys()
return data
Expand Down Expand Up @@ -329,10 +328,10 @@ def btrfs_send(self, subvols, node, incremental=True):
else:
receive_cmd = ["btrfs", "receive", self.dst_next_dir(node)]

self.log.info(" ".join(send_cmd + ["|"] + receive_cmd))
p1 = Popen(send_cmd, stdout=PIPE, stderr=PIPE)
pi = Popen(["dd", "bs=4096"], stdin=p1.stdout, stdout=PIPE, stderr=PIPE)
p2 = Popen(receive_cmd, stdin=pi.stdout, stdout=PIPE, stderr=PIPE)
self.log.info(subprocess.list2cmdline(send_cmd) + " | " + subprocess.list2cmdline(receive_cmd))
p1 = subprocess.Popen(send_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pi = subprocess.Popen(["dd", "bs=4096"], stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen(receive_cmd, stdin=pi.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
buff = p2.communicate()
send_buff = p1.stderr.read()
if send_buff is not None and len(send_buff) > 0:
Expand Down Expand Up @@ -380,7 +379,7 @@ def cleanup_remote(self, node, remote_subvols):
raise ex.Error()

def remove_dst_snap_temp(self, node):
return ["rm -rf %s" % self.dst_temp_dir(node)]
return [subprocess.list2cmdline(["rm", "-rf", self.dst_temp_dir(node)])]

def remove_dst_snap_next(self, node):
o = self.get_btrfs(node)
Expand All @@ -389,7 +388,7 @@ def remove_dst_snap_next(self, node):
cmd = o.subvol_delete_cmd(subvols) or []
if not cmd:
return []
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def remove_dst_snap_last(self, node):
o = self.get_btrfs(node)
Expand All @@ -398,7 +397,7 @@ def remove_dst_snap_last(self, node):
cmd = o.subvol_delete_cmd(subvols) or []
if not cmd:
return []
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def remove_src_snap_last(self):
o = self.get_btrfs()
Expand All @@ -407,20 +406,20 @@ def remove_src_snap_last(self):
cmd = o.subvol_delete_cmd(subvols) or []
if not cmd:
return []
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def rename_src_snap_next(self):
src = self.src_next_dir()
dst = self.src_last_dir()
cmd = ["mv", "-v", src, dst]
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def rename_dst_snap_next(self, node):
src = self.dst_next_dir(node)
dst = self.dst_last_dir(node)
cmds = [
"rm -rf %s" % dst,
"mv -v %s %s" % (src, dst),
subprocess.list2cmdline(["rm", "-rf", dst]),
subprocess.list2cmdline(["mv", "-v", src, dst]),
]
return cmds

Expand All @@ -429,16 +428,16 @@ def remove_dst(self, subvol, node):
cmd = self.dst_btrfs[node].subvol_delete_cmd(dst)
if not cmd:
return []
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def install_final(self, node):
head_subvol = self.subvols()[0]
src = os.path.join(self.dst_temp_dir(node), head_subvol["path"])
if protected_dir(self.dst):
raise ex.Error("%s is a protected dir. refuse to remove" % self.dst)
cmds = [
"rm -rf %s" % self.dst,
"mv -v %s %s" % (src, self.dst),
subprocess.list2cmdline(["rm", "-rf", self.dst]),
subprocess.list2cmdline(["mv", "-v", src, self.dst]),
]
return cmds

Expand All @@ -450,8 +449,8 @@ def install_dst(self, subvols, node):
cmd = self.dst_btrfs[node].snapshot_cmd(src, dst, readonly=False)
if not cmd:
continue
cmds.append("mkdir -p %s" % os.path.dirname(dst))
cmds.append(" ".join(cmd))
cmds.append(subprocess.list2cmdline(["mkdir", "-p", os.path.dirname(dst)]))
cmds.append(subprocess.list2cmdline(cmd))
return cmds

def make_src_workdirs(self):
Expand Down
5 changes: 3 additions & 2 deletions opensvc/drivers/resource/sync/btrfssnap/__init__.py
@@ -1,5 +1,6 @@
import datetime
import os
import subprocess

import core.status
import utilities.subsystems.btrfs
Expand Down Expand Up @@ -178,7 +179,7 @@ def create_snap(self, label, subvol):
cmd = btrfs.snapshot_cmd(orig, snap, readonly=True)
if not cmd:
return []
return [" ".join(cmd)]
return [subprocess.list2cmdline(cmd)]

def remove_snaps(self, label, subvol):
btrfs = self.get_btrfs(label)
Expand All @@ -201,7 +202,7 @@ def remove_snaps(self, label, subvol):
for path in sorted_snaps[self.keep:]:
cmd = btrfs.subvol_delete_cmd(os.path.join(btrfs.rootdir, path))
if cmd:
cmds.append(" ".join(cmd))
cmds.append(subprocess.list2cmdline(cmd))
return cmds

def _status_one(self, label, subvol):
Expand Down
20 changes: 12 additions & 8 deletions opensvc/utilities/subsystems/btrfs.py
@@ -1,6 +1,7 @@
import sys
import os
import logging
import subprocess

import core.exceptions as ex
import utilities.devices.linux
Expand Down Expand Up @@ -131,7 +132,7 @@ def get_subvols(self, refresh=False):
cmd = ['btrfs', 'subvol', 'list', '-qupR', self.path]
out, err, ret = self.justcall(cmd)
if ret != 0:
cmd_string = " ".join(cmd)
cmd_string = subprocess.list2cmdline(cmd)
if self.node is not None:
self.log.warning("command failed on %s: %s", self.node, cmd_string)
raise InitError("error running '%s': %s\n" % (cmd_string, err))
Expand Down Expand Up @@ -212,7 +213,7 @@ def snapshots(self, snaps, readonly=False):
origin = s[0]
snap = s[1]
cmd = ['btrfs', 'subvolume', 'snapshot'] + opts + [origin, snap]
cmds += [" ".join(cmd)]
cmds += [subprocess.list2cmdline(cmd)]
ret, out, err = self.vcall(" && ".join(cmds), shell=True)
if ret != 0:
raise ExecError(err)
Expand Down Expand Up @@ -270,18 +271,21 @@ def mount_rootvol(self):

def vcall(self, cmd, shell=False):
if self.node is not None:
if not shell:
cmd = ' '.join(cmd)
cmd = Env.rsh.split() + [self.node] + [cmd]
lcmd = Env.rsh.split() + [self.node]
if shell:
rcmd = cmd
cmd = lcmd + [rcmd]
cmd = subprocess.list2cmdline(cmd)
else:
cmd = "%s %s \"%s\"" % (Env.rsh, self.node, cmd)
rcmd = subprocess.list2cmdline(cmd)
cmd = lcmd + [rcmd]

return vcall(cmd, log=self.log, shell=shell)

def justcall(self, cmd):
if self.node is not None:
cmd = [' '.join(cmd)]
cmd = Env.rsh.split() + [self.node] + cmd
cmd = subprocess.list2cmdline(cmd)
cmd = Env.rsh.split() + [self.node, cmd]
return justcall(cmd)

def create_subvol(self, path):
Expand Down

0 comments on commit 9caf967

Please sign in to comment.