Skip to content

Commit 3571c2e

Browse files
committed
ensure xud
1 parent df61ee1 commit 3571c2e

File tree

8 files changed

+221
-120
lines changed

8 files changed

+221
-120
lines changed

images/utils/launcher/__init__.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import logging
22
import shlex
33
import traceback
4+
from threading import Event
45

56
from launcher.close_other_utils import Action as CloseOtherUtilsAction
67
from launcher.config import Config
78
from launcher.errors import FatalError, ConfigError, ConfigErrorScope
8-
from launcher.node import NodeManager, ServiceNotFound, ContainerNotFound
9-
from launcher.utils import ParallelExecutionError, ArgumentError
9+
from launcher.node import NodeManager, ServiceNotFound, ContainerNotFound, NoWaiting
10+
from launcher.utils import ArgumentError
1011
import docker.errors
1112
import os
1213

@@ -185,7 +186,15 @@ def pre_shell(self):
185186
print("\n🏃 Warming up...\n")
186187

187188
xud = self.node_manager.get_service("xud")
188-
xud.ensure_ready()
189+
stop = Event()
190+
try:
191+
# FIXME pty signal only works in main thread
192+
xud.ensure_ready(stop)
193+
except KeyboardInterrupt:
194+
stop.set()
195+
raise
196+
except NoWaiting:
197+
pass
189198

190199
self.close_other_utils()
191200

images/utils/launcher/auto_unlock.py

Lines changed: 0 additions & 35 deletions
This file was deleted.

images/utils/launcher/config/config.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -948,13 +948,11 @@ def conf_file(self) -> str:
948948
return os.path.join(self.network_dir, filename)
949949

950950
def parse_network_config(self):
951-
conf = ""
952-
953951
try:
954952
with open(self.conf_file) as f:
955953
conf = f.read()
956954
except FileNotFoundError:
957-
return
955+
conf = ""
958956

959957
parsed = toml.loads(conf)
960958

images/utils/launcher/node/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from launcher.utils import get_hostfs_file, ArgumentParser, yes_or_no
1818
from .DockerTemplate import DockerTemplate
1919
from .arby import Arby
20-
from .base import Node, ContainerNotFound
20+
from .base import Node, ContainerNotFound, NoWaiting
2121
from .bitcoind import Bitcoind, Litecoind
2222
from .boltz import Boltz
2323
from .connext import Connext
@@ -434,4 +434,5 @@ def wrapper(node):
434434

435435
@property
436436
def newly_installed(self):
437-
return not os.path.exists(f"{get_hostfs_file(self.config.network_dir)}/data/xud/nodekey.dat")
437+
xud = self.get_service("xud")
438+
return not xud.has_wallets()

images/utils/launcher/node/base.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
from __future__ import annotations
2+
23
import datetime
34
import itertools
45
import logging
56
import os
6-
from typing import List, Dict, Any, Optional
7+
from threading import Event
8+
from typing import List, Dict, Any, Optional, Tuple
9+
from typing import TYPE_CHECKING
10+
711
import docker
812
from docker import DockerClient
913
from docker.errors import NotFound
1014
from docker.models.containers import Container
11-
from typing import TYPE_CHECKING
1215

1316
from launcher.config import PortPublish
1417
from .image import Image
@@ -19,7 +22,6 @@
1922
from .image import ImageManager
2023
from . import NodeManager
2124

22-
2325
logger = logging.getLogger(__name__)
2426

2527

@@ -33,6 +35,10 @@ class ContainerNotFound(Exception):
3335
pass
3436

3537

38+
class NoWaiting(Exception):
39+
pass
40+
41+
3642
class ContainerSpec:
3743
def __init__(self, name: str, image: Image, hostname: str, environment: List[str], command: List[str],
3844
volumes: Dict, ports: Dict):
@@ -108,6 +114,9 @@ def __init__(self, name: str, ctx):
108114

109115
self._cli = None
110116

117+
def __repr__(self):
118+
return "<Service %s>" % self.name
119+
111120
def generate_environment(self):
112121
environment = [f"NETWORK={self.network}"]
113122
if self.node_config["preserve_config"]:
@@ -251,8 +260,9 @@ def status(self) -> str:
251260
except ContainerNotFound:
252261
return "Container missing"
253262

254-
def exec(self, command: str) -> Any:
255-
return self.container.exec_run(command)
263+
def exec(self, command: str) -> Tuple[int, str]:
264+
exit_code, output = self.container.exec_run(command)
265+
return exit_code, output.decode()
256266

257267
def cli(self, command: str, exception=False) -> None:
258268
if self.mode != "native":
@@ -465,7 +475,7 @@ def get_update_action(self) -> str:
465475
logger.info("Container %s: action=%s", self.container_name, action)
466476
return action
467477

468-
def ensure_ready(self):
478+
def ensure_ready(self, stop: Event) -> None:
469479
pass
470480

471481

images/utils/launcher/node/lnd.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import json
2+
import logging
23
import re
34
from datetime import datetime, timedelta
5+
from threading import Event
46

7+
from launcher.utils import get_percentage
58
from .base import Node, CliBackend, CliError
69

10+
logger = logging.getLogger(__name__)
11+
712

813
class InvalidChain(Exception):
914
def __init__(self, chain: str):
@@ -26,6 +31,20 @@ def getinfo(self):
2631
raise LndApiError(e.output)
2732

2833

34+
class CFHeaderState:
35+
def __init__(self):
36+
self.current = 0
37+
self.total = 0
38+
self.ready = False
39+
40+
def __repr__(self):
41+
return "%s/%s (%s)" % (self.current, self.total, self.ready)
42+
43+
@property
44+
def message(self):
45+
return "Syncing " + get_percentage(self.current, self.total)
46+
47+
2948
class Lnd(Node):
3049
def __init__(self, name, ctx, chain: str):
3150
super().__init__(name, ctx)
@@ -159,6 +178,60 @@ def status(self):
159178
self._logger.exception("Failed to get advanced running status")
160179
return "Waiting for lnd ({}) to come up...".format(self.chain)
161180

181+
def ensure_ready(self, stop: Event):
182+
# [lncli] open /root/.lnd/tls.cert: no such file or directory
183+
# [lncli] unable to read macaroon path (check the network setting!): open /root/.lnd/data/chain/bitcoin/testnet/admin.macaroon: no such file or directory
184+
# [lncli] Wallet is encrypted. Please unlock using 'lncli unlock', or set password using 'lncli create' if this is the first time starting lnd.
185+
while not stop.is_set():
186+
exit_code, output = self.exec(self._cli + " getinfo")
187+
if exit_code == 0:
188+
break
189+
if "unable to read macaroon path" in output:
190+
break
191+
if "Wallet is encrypted" in output:
192+
break
193+
stop.wait(3)
194+
195+
def update_cfheader(self, state: CFHeaderState, stop: Event):
196+
container = self.container
197+
started_at = container.attrs["State"]["StartedAt"] # e.g. 2020-06-22T17:26:01.541780733Z
198+
started_at = started_at.split(".")[0]
199+
t_utc = datetime.strptime(started_at, "%Y-%m-%dT%H:%M:%S")
200+
t_local = datetime.fromtimestamp(t_utc.timestamp())
201+
202+
p0 = re.compile(r"^.*Fully caught up with cfheaders at height (\d+), waiting at tip for new blocks$")
203+
if self.config.network == "simnet":
204+
p1 = re.compile(r"^.*Writing cfheaders at height=(\d+) to next checkpoint$")
205+
else:
206+
p1 = re.compile(r"^.*Fetching set of checkpointed cfheaders filters from height=(\d+).*$")
207+
p2 = re.compile(r"^.*Syncing to block height (\d+) from peer.*$")
208+
209+
if stop.is_set():
210+
return
211+
212+
for line in container.logs(stream=True, follow=True, since=t_local):
213+
if stop.is_set():
214+
break
215+
line = line.decode().strip()
216+
m = p0.match(line)
217+
218+
if m:
219+
state.current = int(m.group(1))
220+
state.ready = True
221+
h = max(state.current, state.total)
222+
state.current = h
223+
state.total = h
224+
break
225+
226+
m = p1.match(line)
227+
if m:
228+
state.current = int(m.group(1))
229+
continue
230+
231+
m = p2.match(line)
232+
if m:
233+
state.total = int(m.group(1))
234+
162235

163236
class Lndbtc(Lnd):
164237
def __init__(self, *args):

0 commit comments

Comments
 (0)