mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 00:13:52 +01:00
Change transport format in zrepl config & parse it.
This commit is contained in:
parent
fd24096137
commit
2d57e15936
@ -3,17 +3,37 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/zrepl/zrepl/rpc"
|
||||||
|
"github.com/zrepl/zrepl/sshbytestream"
|
||||||
"github.com/zrepl/zrepl/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
Name string
|
Name string
|
||||||
Url string
|
Transport Transport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Transport interface {
|
||||||
|
Connect() (rpc.RPCRequester, error)
|
||||||
|
}
|
||||||
|
type LocalTransport struct {
|
||||||
|
Pool string
|
||||||
|
}
|
||||||
|
type SSHTransport struct {
|
||||||
|
ZreplIdentity string
|
||||||
|
Host string
|
||||||
|
User string
|
||||||
|
Port uint16
|
||||||
|
TransportOpenCommand []string
|
||||||
|
Options []string
|
||||||
|
}
|
||||||
|
|
||||||
type Push struct {
|
type Push struct {
|
||||||
To *Pool
|
To *Pool
|
||||||
Datasets []zfs.DatasetPath
|
Datasets []zfs.DatasetPath
|
||||||
@ -77,12 +97,63 @@ func parseMain(root map[string]interface{}) (c Config, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePools(v interface{}) (p []Pool, err error) {
|
func parsePools(v interface{}) (pools []Pool, err error) {
|
||||||
p = make([]Pool, 0)
|
|
||||||
err = mapstructure.Decode(v, &p)
|
asList := make([]struct {
|
||||||
|
Name string
|
||||||
|
Transport map[string]interface{}
|
||||||
|
}, 0)
|
||||||
|
if err = mapstructure.Decode(v, &asList); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pools = make([]Pool, len(asList))
|
||||||
|
for i, p := range asList {
|
||||||
|
var transport Transport
|
||||||
|
if transport, err = parseTransport(p.Transport); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pools[i] = Pool{
|
||||||
|
Name: p.Name,
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseTransport(it map[string]interface{}) (t Transport, err error) {
|
||||||
|
|
||||||
|
if len(it) != 1 {
|
||||||
|
err = errors.New("ambiguous transport type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, val := range it {
|
||||||
|
switch key {
|
||||||
|
case "ssh":
|
||||||
|
t := SSHTransport{}
|
||||||
|
if err = mapstructure.Decode(val, &t); err != nil {
|
||||||
|
err = errors.New(fmt.Sprintf("could not parse ssh transport: %s", err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
case "local":
|
||||||
|
t := LocalTransport{}
|
||||||
|
if err = mapstructure.Decode(val, &t); err != nil {
|
||||||
|
err = errors.New(fmt.Sprintf("could not parse local transport: %s", err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("unknown transport type '%s'\n", key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return // unreachable
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type poolLookup func(name string) (*Pool, error)
|
type poolLookup func(name string) (*Pool, error)
|
||||||
|
|
||||||
func parsePushs(v interface{}, pl poolLookup) (p []Push, err error) {
|
func parsePushs(v interface{}, pl poolLookup) (p []Push, err error) {
|
||||||
@ -244,3 +315,18 @@ func parseComboMapping(m map[string]string) (c zfs.ComboMapping, err error) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t SSHTransport) Connect() (r rpc.RPCRequester, err error) {
|
||||||
|
var stream io.ReadWriteCloser
|
||||||
|
var rpcTransport sshbytestream.SSHTransport
|
||||||
|
copier.Copy(rpcTransport, t)
|
||||||
|
if stream, err = sshbytestream.Outgoing(rpcTransport); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return rpc.ConnectByteStreamRPC(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t LocalTransport) Connect() (r rpc.RPCRequester, err error) {
|
||||||
|
// TODO ugly hidden global variable reference
|
||||||
|
return rpc.ConnectLocalRPC(handler), nil
|
||||||
|
}
|
||||||
|
@ -1,9 +1,18 @@
|
|||||||
pools:
|
pools:
|
||||||
- name: offsite_backups
|
- name: offsite_backups
|
||||||
url: ssh://db2@backups1/db2/
|
transport:
|
||||||
- name:
|
ssh:
|
||||||
|
zrepl_identity: db2
|
||||||
|
host: backups1.example.com
|
||||||
|
user: root
|
||||||
|
port: 22
|
||||||
|
command: ssh
|
||||||
|
args: []
|
||||||
|
|
||||||
- name: local_mirror
|
- name: local_mirror
|
||||||
url: local://mirrorpool/mirrors/tank
|
transport:
|
||||||
|
local:
|
||||||
|
pool: mirrorpool
|
||||||
|
|
||||||
pushs:
|
pushs:
|
||||||
- to: offsite_backups
|
- to: offsite_backups
|
||||||
@ -11,16 +20,17 @@ pushs:
|
|||||||
- tank/var/db
|
- tank/var/db
|
||||||
- tank/usr/home
|
- tank/usr/home
|
||||||
|
|
||||||
- to: local_mirror
|
|
||||||
datasets:
|
|
||||||
- tank
|
|
||||||
|
|
||||||
pulls:
|
pulls:
|
||||||
- from: offsite
|
- from: offsite_backups
|
||||||
mapping: {
|
mapping: {
|
||||||
# like in sinks
|
# like in sinks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- from: local_mirror
|
||||||
|
mapping: {
|
||||||
|
"tank/usr/home":"mirrorpool/foo/bar"
|
||||||
|
}
|
||||||
|
|
||||||
sinks:
|
sinks:
|
||||||
|
|
||||||
# direct mapping
|
# direct mapping
|
||||||
|
Loading…
Reference in New Issue
Block a user