mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-13 11:09:23 +01:00
lncfg+etcd: add namespace support for etcd databases
Since we're now storing the content of multiple previously distinct database files in etcd, we want to properly namespace them as not to provoke any key collisions. We append a sub namespace to the given global namespace in order to still support multiple lnd nodes using the same etcd database simultaneously. Because the btcwallet code uses the legacy walletdb interface we must assume it is not fully concurrency safe. Therefore we make sure only a single writer can be active at any given time for the wallet DB backend when using etcd.
This commit is contained in:
parent
57c7862eeb
commit
1e84b52fee
2 changed files with 124 additions and 7 deletions
|
@ -1,5 +1,7 @@
|
|||
package etcd
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Config holds etcd configuration alongside with configuration related to our higher level interface.
|
||||
type Config struct {
|
||||
Embedded bool `long:"embedded" description:"Use embedded etcd instance instead of the external one. Note: use for testing only."`
|
||||
|
@ -30,3 +32,51 @@ type Config struct {
|
|||
// single writer to the database at a time.
|
||||
SingleWriter bool
|
||||
}
|
||||
|
||||
// CloneWithSubNamespace clones the current configuration and returns a new
|
||||
// instance with the given sub namespace applied by appending it to the main
|
||||
// namespace.
|
||||
func (c *Config) CloneWithSubNamespace(subNamespace string) *Config {
|
||||
ns := c.Namespace
|
||||
if len(ns) == 0 {
|
||||
ns = subNamespace
|
||||
} else {
|
||||
ns = fmt.Sprintf("%s/%s", ns, subNamespace)
|
||||
}
|
||||
|
||||
return &Config{
|
||||
Embedded: c.Embedded,
|
||||
EmbeddedClientPort: c.EmbeddedClientPort,
|
||||
EmbeddedPeerPort: c.EmbeddedPeerPort,
|
||||
Host: c.Host,
|
||||
User: c.User,
|
||||
Pass: c.Pass,
|
||||
Namespace: ns,
|
||||
DisableTLS: c.DisableTLS,
|
||||
CertFile: c.CertFile,
|
||||
KeyFile: c.KeyFile,
|
||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||
CollectStats: c.CollectStats,
|
||||
SingleWriter: c.SingleWriter,
|
||||
}
|
||||
}
|
||||
|
||||
// CloneWithSingleWriter clones the current configuration and returns a new
|
||||
// instance with the single writer property set to true.
|
||||
func (c *Config) CloneWithSingleWriter() *Config {
|
||||
return &Config{
|
||||
Embedded: c.Embedded,
|
||||
EmbeddedClientPort: c.EmbeddedClientPort,
|
||||
EmbeddedPeerPort: c.EmbeddedPeerPort,
|
||||
Host: c.Host,
|
||||
User: c.User,
|
||||
Pass: c.Pass,
|
||||
Namespace: c.Namespace,
|
||||
DisableTLS: c.DisableTLS,
|
||||
CertFile: c.CertFile,
|
||||
KeyFile: c.KeyFile,
|
||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||
CollectStats: c.CollectStats,
|
||||
SingleWriter: true,
|
||||
}
|
||||
}
|
||||
|
|
81
lncfg/db.go
81
lncfg/db.go
|
@ -39,6 +39,9 @@ const (
|
|||
// NSTowerServerDB is the namespace name that we use for the watchtower
|
||||
// server DB.
|
||||
NSTowerServerDB = "towerserverdb"
|
||||
|
||||
// NSWalletDB is the namespace name that we use for the wallet DB.
|
||||
NSWalletDB = "walletdb"
|
||||
)
|
||||
|
||||
// DB holds database configuration for LND.
|
||||
|
@ -173,30 +176,92 @@ func (db *DB) GetBackends(ctx context.Context, chanDBPath,
|
|||
}()
|
||||
|
||||
if db.Backend == EtcdBackend {
|
||||
// As long as the graph data, channel state and height hint
|
||||
// cache are all still in the channel.db file in bolt, we
|
||||
// replicate the same behavior here and use the same etcd
|
||||
// backend for those three sub DBs. But we namespace it properly
|
||||
// to make such a split even easier in the future. This will
|
||||
// break lnd for users that ran on etcd with 0.13.x since that
|
||||
// code used the root namespace. We assume that nobody used etcd
|
||||
// for mainnet just yet since that feature was clearly marked as
|
||||
// experimental in 0.13.x.
|
||||
etcdBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx, db.Etcd,
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.CloneWithSubNamespace(NSChannelDB),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSChannelDB] = etcdBackend.Close
|
||||
|
||||
etcdMacaroonBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.CloneWithSubNamespace(NSMacaroonDB),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd macaroon "+
|
||||
"DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSMacaroonDB] = etcdMacaroonBackend.Close
|
||||
|
||||
etcdDecayedLogBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.CloneWithSubNamespace(NSDecayedLogDB),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd decayed "+
|
||||
"log DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSDecayedLogDB] = etcdDecayedLogBackend.Close
|
||||
|
||||
etcdTowerClientBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.CloneWithSubNamespace(NSTowerClientDB),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd tower "+
|
||||
"client DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSTowerClientDB] = etcdTowerClientBackend.Close
|
||||
|
||||
etcdTowerServerBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.CloneWithSubNamespace(NSTowerServerDB),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd tower "+
|
||||
"server DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSTowerServerDB] = etcdTowerServerBackend.Close
|
||||
|
||||
etcdWalletBackend, err := kvdb.Open(
|
||||
kvdb.EtcdBackendName, ctx,
|
||||
db.Etcd.
|
||||
CloneWithSubNamespace(NSWalletDB).
|
||||
CloneWithSingleWriter(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening etcd macaroon "+
|
||||
"DB: %v", err)
|
||||
}
|
||||
closeFuncs[NSWalletDB] = etcdWalletBackend.Close
|
||||
|
||||
returnEarly = false
|
||||
return &DatabaseBackends{
|
||||
GraphDB: etcdBackend,
|
||||
ChanStateDB: etcdBackend,
|
||||
HeightHintDB: etcdBackend,
|
||||
MacaroonDB: etcdBackend,
|
||||
DecayedLogDB: etcdBackend,
|
||||
TowerClientDB: etcdBackend,
|
||||
TowerServerDB: etcdBackend,
|
||||
MacaroonDB: etcdMacaroonBackend,
|
||||
DecayedLogDB: etcdDecayedLogBackend,
|
||||
TowerClientDB: etcdTowerClientBackend,
|
||||
TowerServerDB: etcdTowerServerBackend,
|
||||
// The wallet loader will attempt to use/create the
|
||||
// wallet in the replicated remote DB if we're running
|
||||
// in a clustered environment. This will ensure that all
|
||||
// members of the cluster have access to the same wallet
|
||||
// state.
|
||||
WalletDB: btcwallet.LoaderWithExternalWalletDB(
|
||||
etcdBackend,
|
||||
etcdWalletBackend,
|
||||
),
|
||||
Remote: true,
|
||||
CloseFuncs: closeFuncs,
|
||||
|
@ -296,7 +361,9 @@ func (db *DB) GetBackends(ctx context.Context, chanDBPath,
|
|||
TowerServerDB: towerServerBackend,
|
||||
// When "running locally", LND will use the bbolt wallet.db to
|
||||
// store the wallet located in the chain data dir, parametrized
|
||||
// by the active network.
|
||||
// by the active network. The wallet loader has its own cleanup
|
||||
// method so we don't need to add anything to our map (in fact
|
||||
// nothing is opened just yet).
|
||||
WalletDB: btcwallet.LoaderWithLocalWalletDB(
|
||||
walletDBPath, !db.Bolt.SyncFreelist, db.Bolt.DBTimeout,
|
||||
),
|
||||
|
|
Loading…
Add table
Reference in a new issue