mirror of
https://github.com/zrepl/zrepl.git
synced 2025-04-02 03:56:18 +02:00
zfs: helper for ZFSGet guid
and createtxg
This commit is contained in:
parent
18d2c350de
commit
0ba4b5eda6
@ -2,7 +2,6 @@ package zfs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -26,30 +25,18 @@ func ZFSGetReplicationCursor(fs *DatasetPath) (*FilesystemVersion, error) {
|
|||||||
func ZFSSetReplicationCursor(fs *DatasetPath, snapname string) (guid uint64, err error) {
|
func ZFSSetReplicationCursor(fs *DatasetPath, snapname string) (guid uint64, err error) {
|
||||||
snapPath := fmt.Sprintf("%s@%s", fs.ToString(), snapname)
|
snapPath := fmt.Sprintf("%s@%s", fs.ToString(), snapname)
|
||||||
debug("replication cursor: snap path %q", snapPath)
|
debug("replication cursor: snap path %q", snapPath)
|
||||||
propsSnap, err := zfsGet(snapPath, []string{"createtxg", "guid"}, sourceAny)
|
snapProps, err := ZFSGetCreateTXGAndGuid(snapPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "zfs: replication cursor: get snapshot createtxg")
|
return 0, errors.Wrapf(err, "get properties of %q", snapPath)
|
||||||
}
|
|
||||||
snapGuid, err := strconv.ParseUint(propsSnap.Get("guid"), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrap(err, "zfs: replication cursor: parse snapshot guid")
|
|
||||||
}
|
}
|
||||||
bookmarkPath := fmt.Sprintf("%s#%s", fs.ToString(), ReplicationCursorBookmarkName)
|
bookmarkPath := fmt.Sprintf("%s#%s", fs.ToString(), ReplicationCursorBookmarkName)
|
||||||
propsBookmark, err := zfsGet(bookmarkPath, []string{"createtxg"}, sourceAny)
|
propsBookmark, err := ZFSGetCreateTXGAndGuid(bookmarkPath)
|
||||||
_, bookmarkNotExistErr := err.(*DatasetDoesNotExist)
|
_, bookmarkNotExistErr := err.(*DatasetDoesNotExist)
|
||||||
if err != nil && !bookmarkNotExistErr {
|
if err != nil && !bookmarkNotExistErr {
|
||||||
return 0, errors.Wrap(err, "zfs: replication cursor: get bookmark txg")
|
return 0, errors.Wrap(err, "zfs: replication cursor: get bookmark txg")
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
bookmarkTxg, err := strconv.ParseUint(propsBookmark.Get("createtxg"), 10, 64)
|
if snapProps.CreateTXG < propsBookmark.CreateTXG {
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrap(err, "zfs: replication cursor: parse bookmark createtxg")
|
|
||||||
}
|
|
||||||
snapTxg, err := strconv.ParseUint(propsSnap.Get("createtxg"), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Wrap(err, "zfs: replication cursor: parse snapshot createtxg")
|
|
||||||
}
|
|
||||||
if snapTxg < bookmarkTxg {
|
|
||||||
return 0, errors.New("zfs: replication cursor: can only be advanced, not set back")
|
return 0, errors.New("zfs: replication cursor: can only be advanced, not set back")
|
||||||
}
|
}
|
||||||
if err := ZFSDestroy(bookmarkPath); err != nil { // FIXME make safer by using new temporary bookmark, then rename, possible with channel programs
|
if err := ZFSDestroy(bookmarkPath); err != nil { // FIXME make safer by using new temporary bookmark, then rename, possible with channel programs
|
||||||
@ -59,5 +46,5 @@ func ZFSSetReplicationCursor(fs *DatasetPath, snapname string) (guid uint64, err
|
|||||||
if err := ZFSBookmark(fs, snapname, ReplicationCursorBookmarkName); err != nil {
|
if err := ZFSBookmark(fs, snapname, ReplicationCursorBookmarkName); err != nil {
|
||||||
return 0, errors.Wrapf(err, "zfs: replication cursor: create bookmark")
|
return 0, errors.Wrapf(err, "zfs: replication cursor: create bookmark")
|
||||||
}
|
}
|
||||||
return snapGuid, nil
|
return snapProps.Guid, nil
|
||||||
}
|
}
|
||||||
|
37
zfs/zfs.go
37
zfs/zfs.go
@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -20,6 +19,7 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/zrepl/zrepl/util/envconst"
|
"github.com/zrepl/zrepl/util/envconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1024,6 +1024,41 @@ func zfsGet(path string, props []string, allowedSources zfsPropertySource) (*ZFS
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ZFSPropCreateTxgAndGuidProps struct {
|
||||||
|
CreateTXG, Guid uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func ZFSGetCreateTXGAndGuid(ds string) (ZFSPropCreateTxgAndGuidProps, error) {
|
||||||
|
props, err := zfsGetNumberProps(ds, []string{"createtxg", "guid"}, sourceAny)
|
||||||
|
if err != nil {
|
||||||
|
return ZFSPropCreateTxgAndGuidProps{}, err
|
||||||
|
}
|
||||||
|
return ZFSPropCreateTxgAndGuidProps{
|
||||||
|
CreateTXG: props["createtxg"],
|
||||||
|
Guid: props["guid"],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns *DatasetDoesNotExist if the dataset does not exist
|
||||||
|
func zfsGetNumberProps(ds string, props []string, src zfsPropertySource) (map[string]uint64, error) {
|
||||||
|
sps, err := zfsGet(ds, props, sourceAny)
|
||||||
|
if err != nil {
|
||||||
|
if _, ok := err.(*DatasetDoesNotExist); ok {
|
||||||
|
return nil, err // pass through as is
|
||||||
|
}
|
||||||
|
return nil, errors.Wrap(err, "zfs: set replication cursor: get snapshot createtxg")
|
||||||
|
}
|
||||||
|
r := make(map[string]uint64, len(props))
|
||||||
|
for _, p := range props {
|
||||||
|
v, err := strconv.ParseUint(sps.Get(p), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "zfs get: parse number property %q", p)
|
||||||
|
}
|
||||||
|
r[p] = v
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
type DestroySnapshotsError struct {
|
type DestroySnapshotsError struct {
|
||||||
RawLines []string
|
RawLines []string
|
||||||
Filesystem string
|
Filesystem string
|
||||||
|
Loading…
Reference in New Issue
Block a user