Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ccaf3b902 | |||
| bcfcd7a134 | |||
| bf1276f767 | |||
| 9fa7a18351 |
@@ -358,7 +358,7 @@ jobs:
|
||||
subcommand: docdep
|
||||
- run:
|
||||
command: |
|
||||
git config --global user.email "me@cschwarz.com"
|
||||
git config --global user.email "zreplbot@cschwarz.com"
|
||||
git config --global user.name "zrepl-github-io-ci"
|
||||
|
||||
# https://circleci.com/docs/2.0/add-ssh-key/#adding-multiple-keys-with-blank-hostnames
|
||||
|
||||
@@ -356,9 +356,17 @@ func renderReplicationReport(t *stringbuilder.B, rep *report.Report, history *by
|
||||
// Progress: [---------------]
|
||||
expected, replicated, containsInvalidSizeEstimates := latest.BytesSum()
|
||||
rate, changeCount := history.Update(replicated)
|
||||
eta := time.Duration(0)
|
||||
if rate > 0 {
|
||||
eta = time.Duration((expected-replicated)/rate) * time.Second
|
||||
}
|
||||
|
||||
t.Write("Progress: ")
|
||||
t.DrawBar(50, replicated, expected, changeCount)
|
||||
t.Write(fmt.Sprintf(" %s / %s @ %s/s", ByteCountBinary(replicated), ByteCountBinary(expected), ByteCountBinary(rate)))
|
||||
if eta != 0 {
|
||||
t.Write(fmt.Sprintf(" (%s remaining)", humanizeDuration(eta)))
|
||||
}
|
||||
t.Newline()
|
||||
if containsInvalidSizeEstimates {
|
||||
t.Write("NOTE: not all steps could be size-estimated, total estimate is likely imprecise!")
|
||||
@@ -383,6 +391,30 @@ func renderReplicationReport(t *stringbuilder.B, rep *report.Report, history *by
|
||||
}
|
||||
}
|
||||
|
||||
func humanizeDuration(duration time.Duration) string {
|
||||
days := int64(duration.Hours() / 24)
|
||||
hours := int64(math.Mod(duration.Hours(), 24))
|
||||
minutes := int64(math.Mod(duration.Minutes(), 60))
|
||||
seconds := int64(math.Mod(duration.Seconds(), 60))
|
||||
|
||||
var parts []string
|
||||
|
||||
force := false
|
||||
chunks := []int64{days, hours, minutes, seconds}
|
||||
for i, chunk := range chunks {
|
||||
if force || chunk > 0 {
|
||||
padding := 0
|
||||
if force {
|
||||
padding = 2
|
||||
}
|
||||
parts = append(parts, fmt.Sprintf("%*d%c", padding, chunk, "dhms"[i]))
|
||||
force = true
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
func renderPrunerReport(t *stringbuilder.B, r *pruner.Report, fsfilter FilterFunc) {
|
||||
if r == nil {
|
||||
t.Printf("...\n")
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# quick start section which inlines this example.
|
||||
#
|
||||
# CUSTOMIZATIONS YOU WILL LIKELY WANT TO APPLY:
|
||||
# - adjust the name of the production pool `system` in the `filesystems` filter of jobs `snapjob` and `push_to_derive`
|
||||
# - adjust the name of the production pool `system` in the `filesystems` filter of jobs `snapjob` and `push_to_drive`
|
||||
# - adjust the name of the backup pool `backuppool` in the `backuppool_sink` job
|
||||
# - adjust the occurences of `myhostname` to the name of the system you are backing up (cannot be easily changed once you start replicating)
|
||||
# - make sure the `zrepl_` prefix is not being used by any other zfs tools you might have installed (it likely isn't)
|
||||
@@ -85,4 +85,4 @@ jobs:
|
||||
root_fs: "backuppool/zrepl/sink"
|
||||
serve:
|
||||
type: local
|
||||
listener_name: backuppool_sink
|
||||
listener_name: backuppool_sink
|
||||
|
||||
+12
-9
@@ -1,6 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NON_INTERACTIVE=false
|
||||
DO_CLONE=false
|
||||
@@ -13,7 +12,7 @@ while getopts "ca" arg; do
|
||||
DO_CLONE=true
|
||||
;;
|
||||
*)
|
||||
echo invalid option
|
||||
echo "invalid option '-$arg'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -27,11 +26,6 @@ checkout_repo_msg() {
|
||||
echo "clone ${GHPAGESREPO} to ${PUBLICDIR}:"
|
||||
}
|
||||
|
||||
exit_msg() {
|
||||
echo "error, exiting..."
|
||||
}
|
||||
trap exit_msg EXIT
|
||||
|
||||
if ! type sphinx-versioning >/dev/null; then
|
||||
echo "install sphinx-versioning and come back"
|
||||
exit 1
|
||||
@@ -71,6 +65,9 @@ git reset --hard origin/master
|
||||
|
||||
echo "cleaning GitHub pages repo"
|
||||
git rm -rf .
|
||||
cat > .gitignore <<EOF
|
||||
**/.doctrees
|
||||
EOF
|
||||
|
||||
popd
|
||||
|
||||
@@ -96,7 +93,13 @@ COMMIT_MSG="sphinx-versioning render from publish.sh - $(date -u) - ${CURRENT_CO
|
||||
pushd "$PUBLICDIR"
|
||||
|
||||
echo "adding and commiting all changes in GitHub pages repo"
|
||||
git add .gitignore
|
||||
git add -A
|
||||
git commit -m "$COMMIT_MSG"
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
git commit -m "$COMMIT_MSG"
|
||||
else
|
||||
echo "nothing to commit"
|
||||
fi
|
||||
echo "pushing to GitHub pages repo"
|
||||
git push origin master
|
||||
|
||||
|
||||
@@ -90,6 +90,40 @@ func ZFSCreatePlaceholderFilesystem(ctx context.Context, fs *DatasetPath, parent
|
||||
"-o", fmt.Sprintf("%s=%s", PlaceholderPropertyName, placeholderPropertyOn),
|
||||
"-o", "mountpoint=none",
|
||||
}
|
||||
|
||||
// xxx handle encryption not supported
|
||||
props, err := zfsGet(ctx, parent.ToString(), []string{"keystatus"}, SourceAny)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot determine key status")
|
||||
}
|
||||
keystatus := props.Get("keystatus") // xxx ability to distringuish `-` from ``
|
||||
if keystatus == "" {
|
||||
// parent is unencrypted => placeholder inherits encryption
|
||||
} else if keystatus == "available" {
|
||||
// parent is encrypted but since the key is loaded we can create an encrypted placeholder dataset
|
||||
// without `-o encryption=off`
|
||||
} else if keystatus == "unavailable" {
|
||||
// parent is encrypted but keys are not loaded, either because
|
||||
// 1) it's a send-encrypted dataset, or because
|
||||
// 2) the user forgot to zfs load-key the root_fs or above
|
||||
// In both cases we can't create an encrypted placeholder dataset.
|
||||
// In case 1), we want to create an unencrypted placeholder through `-o encryption=off`.
|
||||
// In case 2), `-o encryption=off` is harmful security-wise because it breaks the encrypt-on-receiver use case (https://github.com/zrepl/zrepl/issues/504)
|
||||
// I.e., all children of the placeholder won't be encrypted because they inherit encryption=off
|
||||
//
|
||||
// => we could attempt to distinguish the cases by being more context sensitive
|
||||
// (i.e., check whether the encryption root is root_fs or a parent thereof)
|
||||
// However, that's always going to be imprecise, and a wrong decision there is harmful security-wise.
|
||||
//
|
||||
// => thus the safe choice is to never use `-o encryption=off` by default
|
||||
// only if we know for sure that the stream is encrypted should we create placeholders with `-o encryption=off`
|
||||
// => this knowledge can be achieved through one of the following means:
|
||||
// a) have the sender indicate it to us in the RPC request (it's ok to trust them in this particular case since lying only hurts _their_ data's confidentiality)
|
||||
// b) have the user acknowledge it in the receiver config
|
||||
} else {
|
||||
return errors.Errorf("unknown keystatus value %q for dataset %q", keystatus, parent.ToString())
|
||||
}
|
||||
|
||||
if parentEncrypted, err := ZFSGetEncryptionEnabled(ctx, parent.ToString()); err != nil {
|
||||
return errors.Wrap(err, "cannot determine encryption support")
|
||||
} else if parentEncrypted {
|
||||
|
||||
Reference in New Issue
Block a user