mirror of https://github.com/jimsalterjrs/sanoid
Compare commits
10 Commits
66fbfe06b4
...
e51fce25d3
| Author | SHA1 | Date |
|---|---|---|
|
|
e51fce25d3 | |
|
|
dbcaeef1ac | |
|
|
2c98f0501c | |
|
|
0f3a9c94d9 | |
|
|
f70a961d79 | |
|
|
d493ef7592 | |
|
|
876685a636 | |
|
|
b1c2bcf859 | |
|
|
41ee154d2c | |
|
|
a61808d3bf |
86
INSTALL.md
86
INSTALL.md
|
|
@ -8,7 +8,8 @@
|
|||
- [Debian/Ubuntu](#debianubuntu)
|
||||
- [RHEL/CentOS/AlmaLinux](#RHEL/CentOS/AlmaLinux)
|
||||
- [FreeBSD](#freebsd)
|
||||
- [Alpine Linux / busybox](#alpine-Linux-busybox-based-distributions)
|
||||
- [Alpine Linux / busybox](#alpine-Linux-or-busybox-based-distributions)
|
||||
- [OmniOS](#OmniOS)
|
||||
- [Other OSes](#other-oses)
|
||||
- [Configuration](#configuration)
|
||||
- [Sanoid](#sanoid)
|
||||
|
|
@ -175,13 +176,88 @@ pkg install p5-Config-Inifiles p5-Capture-Tiny pv mbuffer lzop sanoid
|
|||
|
||||
* See note about tcsh unpleasantness and other things in FREEBSD.readme
|
||||
|
||||
## Alpine Linux / busybox based distributions
|
||||
## OmniOS
|
||||
|
||||
The busybox implementation of ps is lacking needed arguments so a proper ps program needs to be installed.
|
||||
For Alpine Linux this can be done with:
|
||||
Used with OmniOS r34, r36 and r37 (with napp-it installed). Hence, we presume you have a standard perl installation etc.
|
||||
|
||||
`apk --no-cache add procps`
|
||||
1. Install prerequisites: Perl module Config::IniFiles, ssh, pv, gzip, lzop, and mbuffer
|
||||
|
||||
```bash
|
||||
# install/update standard programs
|
||||
pfexec pkg install openssh gzip mbuffer pipe-viewer
|
||||
|
||||
# include OpenCSW repository
|
||||
pfexec pkg set-publisher -G '*' -g https://sfe.opencsw.org/localhostomnios localhostomnios
|
||||
|
||||
# install LZOP (from OpenCSW)
|
||||
pfexec pkg install lzop
|
||||
|
||||
# install Perl modules
|
||||
pfexec perl -MCPAN -e shell
|
||||
install CPAN ## update CPAN
|
||||
reload cpan ## reload
|
||||
|
||||
install inc::latest ## not sure if required
|
||||
install IO::Scalar ## not sure if required
|
||||
install Config::IniFiles
|
||||
install Capture::Tiny
|
||||
install Data::Dumper ## not sure if required, may be installed already
|
||||
install File::Path ## not sure if required, may be installed already
|
||||
install Getopt::Long ## not sure if required
|
||||
install Pod::Usage ## not sure if required
|
||||
install Time::Local ## not sure if required
|
||||
exit
|
||||
```
|
||||
|
||||
2. Download and clone the Sanoid repo:
|
||||
|
||||
```bash
|
||||
# install git
|
||||
pfexec pkg install git
|
||||
|
||||
# Tip: download the repo as root to avoid changing permissions later
|
||||
pfexec git clone https://github.com/jimsalterjrs/sanoid.git
|
||||
cd sanoid
|
||||
|
||||
# checkout latest stable release or stay on master for bleeding edge stuff (but expect bugs!)
|
||||
pfexec git checkout $(git tag | grep "^v" | tail -n 1)
|
||||
|
||||
# patch syncoid, so that it correctly recognises the "zfs resume" capability under OmniOS (see https://github.com/jimsalterjrs/sanoid/issues/554)
|
||||
<< $avail{'sourceresume'} = system("$sourcessh $resumechkcmd $srcpool 2>/dev/null | grep '\\(active\\|enabled\\)' >/dev/null 2>&1");
|
||||
>> $avail{'sourceresume'} = system("$sourcessh $resumechkcmd $srcpool 2>/dev/null | grep -E '^(active|enabled)' >/dev/null 2>&1");
|
||||
<< $avail{'targetresume'} = system("$targetssh $resumechkcmd $dstpool 2>/dev/null | grep '\\(active\\|enabled\\)' >/dev/null 2>&1");
|
||||
>> $avail{'targetresume'} = system("$targetssh $resumechkcmd $dstpool 2>/dev/null | grep -E '^(active|enabled)' >/dev/null 2>&1");
|
||||
|
||||
# most likely not required, but make the executables eXecutable
|
||||
pfexec chmod +x sanoid syncoid findoid sleepymutex
|
||||
|
||||
# Install the executables into /opt/sanoid
|
||||
pfexec mkdir /opt/sanoid
|
||||
pfexec cp sanoid syncoid findoid sleepymutex /opt/sanoid
|
||||
|
||||
# add symbolic links to executables to a directory in $path
|
||||
pfexec ln -s /opt/sanoid/sanoid /usr/bin/sanoid & pfexec ln -s /opt/sanoid/syncoid /usr/bin/syncoid & pfexec ln -s /opt/sanoid/findoid /usr/bin/findoid & pfexec ln -s /opt/sanoid/sleepymutex /usr/bin/sleepymutex
|
||||
```
|
||||
|
||||
3. Create the config directory /etc/sanoid, put default sanoid files there, and create and edit sanoid.conf:
|
||||
```bash
|
||||
# Create the config directory
|
||||
pfexec mkdir /etc/sanoid
|
||||
|
||||
# Copy default config and sample config
|
||||
pfexec cp sanoid.defaults.conf sanoid.conf /etc/sanoid/sanoid.example.conf
|
||||
|
||||
# Create a blank config file
|
||||
pfexec touch /etc/sanoid/sanoid.conf
|
||||
## and edit it (using e.g. nano as editor):
|
||||
pfexec nano /etc/sanoid/sanoid.conf
|
||||
```
|
||||
|
||||
Further steps (not OmniOS specific):
|
||||
- set up SSH connections between two remote hosts
|
||||
- create a cron job that runs sanoid --cron --quiet periodically
|
||||
|
||||
=======
|
||||
## MacOS
|
||||
|
||||
Install prerequisite software:
|
||||
|
|
|
|||
94
syncoid
94
syncoid
|
|
@ -27,7 +27,7 @@ GetOptions(\%args, "no-command-checks", "monitor-version", "compress=s", "dumpsn
|
|||
"no-clone-handling", "no-privilege-elevation", "force-delete", "no-rollback", "create-bookmark", "use-hold",
|
||||
"pv-options=s" => \$pvoptions, "keep-sync-snap", "preserve-recordsize", "mbuffer-size=s" => \$mbuffer_size,
|
||||
"delete-target-snapshots", "insecure-direct-connection=s", "preserve-properties",
|
||||
"include-snaps=s@", "exclude-snaps=s@", "exclude-datasets=s@")
|
||||
"include-snaps=s@", "exclude-snaps=s@", "exclude-datasets=s@", "target-properties=s@", "restore-properties")
|
||||
or pod2usage(2);
|
||||
|
||||
my %compressargs = %{compressargset($args{'compress'} || 'default')}; # Can't be done with GetOptions arg, as default still needs to be set
|
||||
|
|
@ -42,6 +42,12 @@ if (defined($args{'exclude'})) {
|
|||
}
|
||||
}
|
||||
|
||||
if (defined $args{'restore-properties'} && defined $args{'preserve-properties'}) {
|
||||
writelog('WARN', "invalid argument combination, --restore-properties and --preserve-properties aren't compatible!");
|
||||
pod2usage(2);
|
||||
exit 127;
|
||||
}
|
||||
|
||||
my @sendoptions = ();
|
||||
if (length $args{'sendoptions'}) {
|
||||
@sendoptions = parsespecialoptions($args{'sendoptions'});
|
||||
|
|
@ -912,15 +918,58 @@ sub runsynccmd {
|
|||
# if no rollbacks are allowed, disable forced receive
|
||||
if (!defined $args{'no-rollback'}) { $recvoptions .= ' -F'; }
|
||||
|
||||
if (defined $args{'preserve-properties'}) {
|
||||
my %properties = getlocalzfsvalues($sourcehost,$sourcefs,$sourceisroot);
|
||||
|
||||
if (defined $args{'restore-properties'}) {
|
||||
foreach my $key (keys %properties) {
|
||||
my $value = $properties{$key};
|
||||
my ($skey, $ikey) = split(/:/, $key);
|
||||
if (!length($ikey)) {
|
||||
my $skeypresent = 0;
|
||||
foreach my $key1 (keys %properties) {
|
||||
my ($skey1, $ikey1) = split(/:/, $key1);
|
||||
if (length($ikey1)) {
|
||||
if($ikey1 eq $key) {
|
||||
$skeypresent = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$skeypresent) {
|
||||
if(!istargetpropertypresent($key)) {
|
||||
writelog('DEBUG', "will set $key to $value ...");
|
||||
my $pair = escapeshellparam("$key=$value");
|
||||
$recvoptions .= " -o $pair";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!istargetpropertypresent($ikey)) {
|
||||
if($value eq "*default*") {
|
||||
writelog('DEBUG', "will unset $ikey ...");
|
||||
$recvoptions .= " -x $ikey";
|
||||
} else {
|
||||
writelog('DEBUG', "will set $ikey to $value ...");
|
||||
my $pair = escapeshellparam("$ikey=$value");
|
||||
$recvoptions .= " -o $pair";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $args{'preserve-properties'}) {
|
||||
foreach my $key (keys %properties) {
|
||||
my $value = $properties{$key};
|
||||
if(!istargetpropertypresent($key)) {
|
||||
writelog('DEBUG', "will set $key to $value ...");
|
||||
my $pair = escapeshellparam("$key=$value");
|
||||
$recvoptions .= " -o $pair";
|
||||
} else {
|
||||
my $newkey .= "syncoid:$key";
|
||||
writelog('DEBUG', "will set $newkey to $value ...");
|
||||
my $pair = escapeshellparam("$newkey=$value");
|
||||
$recvoptions .= " -o $pair";
|
||||
}
|
||||
}
|
||||
} elsif (defined $args{'preserve-recordsize'}) {
|
||||
my $type = getzfsvalue($sourcehost,$sourcefs,$sourceisroot,'type');
|
||||
if ($type eq "filesystem") {
|
||||
|
|
@ -929,6 +978,26 @@ sub runsynccmd {
|
|||
}
|
||||
}
|
||||
|
||||
if (defined $args{'target-properties'}) {
|
||||
my $props = $args{'target-properties'};
|
||||
foreach (@$props) {
|
||||
my ($tkey, $tvalue) = split(/=/);
|
||||
my $tpair = escapeshellparam("$tkey=$tvalue");
|
||||
$recvoptions .= " -o $tpair";
|
||||
my $localpresent = 0;
|
||||
foreach my $key (keys %properties) {
|
||||
my $value = $properties{$key};
|
||||
if ($tkey eq $key) {
|
||||
$localpresent = 1;
|
||||
}
|
||||
}
|
||||
if(!$localpresent && defined $args{'preserve-properties'}) {
|
||||
$tpair = escapeshellparam("syncoid:$tkey=*default*");
|
||||
$recvoptions .= " -o $tpair";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $sendcmd = "$sourcesudocmd $zfscmd send $sendoptions $sendsource";
|
||||
my $recvcmd = "$targetsudocmd $zfscmd receive $recvoptions $targetfsescaped 2>&1";
|
||||
|
||||
|
|
@ -2331,6 +2400,23 @@ sub writelog {
|
|||
}
|
||||
}
|
||||
|
||||
sub istargetpropertypresent {
|
||||
my ($propname) = @_;
|
||||
|
||||
if (defined $args{'target-properties'}) {
|
||||
my $props = $args{'target-properties'};
|
||||
foreach (@$props) {
|
||||
my ($tkey, $tvalue) = split(/=/);
|
||||
if ($propname =~ /$tkey/) {
|
||||
writelog('DEBUG', "source property $propname will be overwritten by value set in target-properties /$_/");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub snapisincluded {
|
||||
my ($snapname) = @_;
|
||||
|
||||
|
|
@ -2414,7 +2500,9 @@ Options:
|
|||
--create-bookmark Creates a zfs bookmark for the newest snapshot on the source after replication succeeds (only works with --no-sync-snap)
|
||||
--use-hold Adds a hold to the newest snapshot on the source and target after replication succeeds and removes the hold after the next successful replication. The hold name includes the identifier if set. This allows for separate holds in case of multiple targets
|
||||
--preserve-recordsize Preserves the recordsize on initial sends to the target
|
||||
--preserve-properties Preserves locally set dataset properties similar to the zfs send -p flag but this one will also work for encrypted datasets in non raw sends
|
||||
--preserve-properties Preserves locally set dataset properties similar to the zfs send -p flag but this one will also work for encrypted datasets in non raw sends. If --target-properties overrides locally set property, it will be saved with 'syncoid:' prefix on target dataset.
|
||||
--restore-properties Works like --preserve-properties but also sets properties present locally with 'syncoid:' prefix on target dataset (without this prefix).
|
||||
--target-properties Set properties on target dataset, for example --target-properties=canmount=noauto. Can be specified multiple times. The properties defined by this parameter override the properties set by --preserve-properties and --restore-properties.
|
||||
--no-rollback Does not rollback snapshots on target (it probably requires a readonly target)
|
||||
--delete-target-snapshots With this argument snapshots which are missing on the source will be destroyed on the target. Use this if you only want to handle snapshots on the source.
|
||||
--exclude=REGEX DEPRECATED. Equivalent to --exclude-datasets, but will be removed in a future release. Ignored if --exclude-datasets is also provided.
|
||||
|
|
|
|||
Loading…
Reference in New Issue