db4e 0.48.2__tar.gz → 0.48.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. {db4e-0.48.2 → db4e-0.48.3}/PKG-INFO +4 -7
  2. {db4e-0.48.2 → db4e-0.48.3}/db4e/Db4E.tcss +86 -55
  3. {db4e-0.48.2 → db4e-0.48.3}/db4e/Db4EClient.py +15 -11
  4. {db4e-0.48.2 → db4e-0.48.3}/db4e/Db4EServer.py +32 -25
  5. {db4e-0.48.2 → db4e-0.48.3}/db4e/bin/db4e-initial-setup.sh +11 -11
  6. db4e-0.48.3/db4e/client/HealthClient.py +54 -0
  7. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DDef.py +4 -2
  8. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DElem.py +3 -0
  9. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DField.py +1 -0
  10. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DForm.py +1 -0
  11. db4e-0.48.3/db4e/constants/DHealth.py +32 -0
  12. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DLabel.py +17 -5
  13. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DMethod.py +2 -0
  14. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DModule.py +2 -0
  15. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DSQL.py +7 -0
  16. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DStatus.py +12 -0
  17. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DSystemD.py +3 -0
  18. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/BaseDb.py +12 -1
  19. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/DeplDb.py +7 -3
  20. db4e-0.48.3/db4e/db/HealthDb.py +133 -0
  21. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/SQLDb.py +4 -0
  22. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/APIMgr.py +35 -3
  23. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/DeplMgr.py +10 -0
  24. db4e-0.48.3/db4e/mgr/HealthMgr.py +205 -0
  25. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/InstallMgr.py +110 -60
  26. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/RouteMgr.py +18 -6
  27. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/ChainPane.py +39 -3
  28. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/Db4EPane.py +11 -11
  29. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/DonationsPane.py +9 -8
  30. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/InitialSetupPane.py +5 -6
  31. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/MoneroDPane.py +6 -7
  32. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/MoneroDRemotePane.py +11 -11
  33. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/P2PoolPane.py +7 -8
  34. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/P2PoolRemotePane.py +6 -7
  35. db4e-0.48.3/db4e/panes/TUILogPane.py +143 -0
  36. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/WelcomePane.py +4 -5
  37. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/XMRigPane.py +8 -9
  38. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/XMRigRemotePane.py +5 -6
  39. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/BaseMonero.py +6 -13
  40. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/P2PoolInternal.py +15 -0
  41. {db4e-0.48.2 → db4e-0.48.3}/db4e/sync/SyncClient.py +110 -86
  42. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/bin/p2pool +0 -0
  43. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/systemd/p2pool@.service +6 -3
  44. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/systemd/p2pool@.socket +1 -4
  45. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/Db4ELogger.py +10 -4
  46. db4e-0.48.3/db4e/util/Db4ESystemD.py +161 -0
  47. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/Helper.py +62 -16
  48. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/NavHandler.py +29 -12
  49. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/Clock.py +21 -8
  50. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/NavPane.py +19 -26
  51. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/TopBar.py +24 -8
  52. {db4e-0.48.2 → db4e-0.48.3}/pyproject.toml +17 -19
  53. db4e-0.48.2/db4e/panes/TUILogPane.py +0 -108
  54. db4e-0.48.2/db4e/util/ConstGroup.py +0 -112
  55. db4e-0.48.2/db4e/util/Db4ESystemD.py +0 -289
  56. {db4e-0.48.2 → db4e-0.48.3}/LICENSE +0 -0
  57. {db4e-0.48.2 → db4e-0.48.3}/README.md +0 -0
  58. {db4e-0.48.2 → db4e-0.48.3}/db4e/bin/db4e-backup.sh +0 -0
  59. {db4e-0.48.2 → db4e-0.48.3}/db4e/bin/db4e-install-service.sh +0 -0
  60. {db4e-0.48.2 → db4e-0.48.3}/db4e/bin/db4e-metrics.sh +0 -0
  61. {db4e-0.48.2 → db4e-0.48.3}/db4e/bin/db4e-uninstall-service.sh +0 -0
  62. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DButton.py +0 -0
  63. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DDebug.py +0 -0
  64. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DDir.py +0 -0
  65. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DFile.py +0 -0
  66. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DJob.py +0 -0
  67. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DMining.py +0 -0
  68. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DOps.py +0 -0
  69. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DPane.py +0 -0
  70. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DPlaceholder.py +0 -0
  71. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DSelect.py +0 -0
  72. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DSync.py +0 -0
  73. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/DUvicorn.py +0 -0
  74. {db4e-0.48.2 → db4e-0.48.3}/db4e/constants/__init__.py +0 -0
  75. {db4e-0.48.2 → db4e-0.48.3}/db4e/data_migration.py +0 -0
  76. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/MiningDb.py +0 -0
  77. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/MiningETL.py +0 -0
  78. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/OpsDb.py +0 -0
  79. {db4e-0.48.2 → db4e-0.48.3}/db4e/db/OpsETL.py +0 -0
  80. {db4e-0.48.2 → db4e-0.48.3}/db4e/enable_mre.py +0 -0
  81. {db4e-0.48.2 → db4e-0.48.3}/db4e/messages/Db4EMsg.py +0 -0
  82. {db4e-0.48.2 → db4e-0.48.3}/db4e/messages/Quit.py +0 -0
  83. {db4e-0.48.2 → db4e-0.48.3}/db4e/messages/RefreshNavPane.py +0 -0
  84. {db4e-0.48.2 → db4e-0.48.3}/db4e/messages/UpdateTopBar.py +0 -0
  85. {db4e-0.48.2 → db4e-0.48.3}/db4e/messages/__init__.py +0 -0
  86. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/BootstrapMgr.py +0 -0
  87. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/ConfigMgr.py +0 -0
  88. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/PaneMgr.py +0 -0
  89. {db4e-0.48.2 → db4e-0.48.3}/db4e/mgr/__init__.py +0 -0
  90. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/ChainBlocksFoundPane.py +0 -0
  91. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/ChainHashratesPane.py +0 -0
  92. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/LogViewPane.py +0 -0
  93. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/P2PoolHashratesPane.py +0 -0
  94. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/P2PoolSharesFoundPane.py +0 -0
  95. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/P2PoolTablesPane.py +0 -0
  96. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/PaymentsPane.py +0 -0
  97. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/ResultsPane.py +0 -0
  98. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/RuntimePane.py +0 -0
  99. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/XMRigHashratesPane.py +0 -0
  100. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/XMRigSharesFoundPane.py +0 -0
  101. {db4e-0.48.2 → db4e-0.48.3}/db4e/panes/__init__.py +0 -0
  102. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/BaseElem.py +0 -0
  103. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/BaseHourlyMining.py +0 -0
  104. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/BaseMining.py +0 -0
  105. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/BlockFoundEvent.py +0 -0
  106. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/ChainHashrate.py +0 -0
  107. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/ChainMiners.py +0 -0
  108. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/MinerHashrate.py +0 -0
  109. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/PoolHashrate.py +0 -0
  110. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/ShareFoundEvent.py +0 -0
  111. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/SharePosition.py +0 -0
  112. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/mining/XMRPayment.py +0 -0
  113. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/BaseP2Pool.py +0 -0
  114. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/Db4E.py +0 -0
  115. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/LocalMonero.py +0 -0
  116. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/MoneroD.py +0 -0
  117. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/MoneroDRemote.py +0 -0
  118. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/P2Pool.py +0 -0
  119. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/P2PoolRemote.py +0 -0
  120. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/XMRig.py +0 -0
  121. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/monero/XMRigRemote.py +0 -0
  122. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/ops/BaseOps.py +0 -0
  123. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/ops/CurrentUptime.py +0 -0
  124. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/ops/TUILogLine.py +0 -0
  125. {db4e-0.48.2 → db4e-0.48.3}/db4e/recs/ops/TotalUptime.py +0 -0
  126. {db4e-0.48.2 → db4e-0.48.3}/db4e/sync/BaseSync.py +0 -0
  127. {db4e-0.48.2 → db4e-0.48.3}/db4e/sync/SyncServer.py +0 -0
  128. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/__init__.py +0 -0
  129. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/db4e/conf/db4e-logrotate.conf +0 -0
  130. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/db4e/systemd/db4e.service +0 -0
  131. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/monerod/bin/monerod +0 -0
  132. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/monerod/bin/start-monerod.sh +0 -0
  133. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/monerod/conf/monerod.ini +0 -0
  134. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/monerod/systemd/monerod@.service +0 -0
  135. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/monerod/systemd/monerod@.socket +0 -0
  136. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/bin/start-p2pool.sh +0 -0
  137. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/conf/p2pool-logrotate.conf +0 -0
  138. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/conf/p2pool.ini +0 -0
  139. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/docs/LICENSE +0 -0
  140. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/p2pool/docs/README.md +0 -0
  141. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/xmrig/bin/xmrig +0 -0
  142. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/xmrig/conf/config.json +0 -0
  143. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/xmrig/conf/xmrig-logrotate.conf +0 -0
  144. {db4e-0.48.2 → db4e-0.48.3}/db4e/templates/xmrig/systemd/xmrig@.service +0 -0
  145. {db4e-0.48.2 → db4e-0.48.3}/db4e/test_barchart.py +0 -0
  146. {db4e-0.48.2 → db4e-0.48.3}/db4e/test_etl.py +0 -0
  147. {db4e-0.48.2 → db4e-0.48.3}/db4e/test_plot.py +0 -0
  148. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/FormChecker.py +0 -0
  149. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/P2PoolWatcher.py +0 -0
  150. {db4e-0.48.2 → db4e-0.48.3}/db4e/util/PaneCatalogue.py +0 -0
  151. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/BarChart.py +0 -0
  152. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/Db4EPlot.py +0 -0
  153. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/DetailPane.py +0 -0
  154. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/HashratePlot.py +0 -0
  155. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/SharesFoundPlot.py +0 -0
  156. {db4e-0.48.2 → db4e-0.48.3}/db4e/widgets/__init__.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: db4e
3
- Version: 0.48.2
4
- Summary: A unified Monero XMR mining dashboard for deployment, operation and real-time analytics.
3
+ Version: 0.48.3
4
+ Summary: A unified Monero (XMR) mining dashboard for deployment, operations, and real-time analytics.
5
5
  License: GPL-3.0-or-later
6
6
  License-File: LICENSE
7
7
  Keywords: monero,mining,textual,dashboard,analytics
8
8
  Author: Nadim-Daniel Ghaznavi
9
9
  Author-email: nghaznavi@gmail.com
10
- Requires-Python: >=3.10,<3.14
10
+ Requires-Python: >=3.11,<3.14
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Environment :: Console
13
13
  Classifier: Intended Audience :: Developers
@@ -15,7 +15,6 @@ Classifier: Intended Audience :: System Administrators
15
15
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
@@ -27,10 +26,9 @@ Requires-Dist: httpx (>=0.28.1,<0.29.0)
27
26
  Requires-Dist: loguru (>=0.7.3,<0.8.0)
28
27
  Requires-Dist: myloginpath (>=0.0.4,<0.0.5)
29
28
  Requires-Dist: orjson (>=3.10.15,<4.0.0)
30
- Requires-Dist: plotext (>=5.3.2,<6.0.0)
31
29
  Requires-Dist: psutil (>=7.0.0,<8.0.0)
32
30
  Requires-Dist: pydantic (>=2.12.2,<3.0.0)
33
- Requires-Dist: pymongo (>=4.13.2,<5.0.0)
31
+ Requires-Dist: pystemd (>=0.15.3,<0.16.0)
34
32
  Requires-Dist: pytest-asyncio (>=1.2.0,<2.0.0)
35
33
  Requires-Dist: requests (>=2.32.3,<3.0.0)
36
34
  Requires-Dist: rich (>=14.0.0,<15.0.0)
@@ -43,7 +41,6 @@ Requires-Dist: sphinxcontrib-serializinghtml (>=2.0.0,<3.0.0)
43
41
  Requires-Dist: sqlite-utils (>=3.35,<4.0)
44
42
  Requires-Dist: textual-dev (>=1.7.0,<2.0.0)
45
43
  Requires-Dist: textual-plot (>=0.10.1,<0.11.0)
46
- Requires-Dist: textual-plotext (>=1.0.1,<2.0.0)
47
44
  Requires-Dist: textual[syntax] (>=8.2.0,<9.0.0)
48
45
  Requires-Dist: tomli_w (>=1.2.0,<2.0.0)
49
46
  Requires-Dist: uvicorn (>=0.37.0,<0.38.0)
@@ -4,14 +4,28 @@ Screen {
4
4
  background: black;
5
5
  layout: grid;
6
6
  grid-size: 2;
7
- grid-columns: 2fr 7fr;
8
- grid-rows: 13fr 1fr;
7
+ grid-columns: 30 130;
8
+ grid-rows: 40 3;
9
9
  grid-gutter: 0 1; }
10
10
 
11
+ NavPane {
12
+ padding: 0 2;
13
+ width: 30;
14
+ border: round #2aa5ce;
15
+ background: black; }
16
+
17
+ TopBar {
18
+ height: 3;
19
+ width: 161;
20
+ padding: 0 2;
21
+ border: round #2aa5ce;
22
+ dock: top;
23
+ background: black }
24
+
11
25
  Clock {
12
26
  height: 3;
13
27
  padding: 0 2;
14
- border: round #0c323e;
28
+ border: round #2aa5ce;
15
29
  align: center middle;
16
30
  background: black; }
17
31
 
@@ -31,25 +45,12 @@ PlotWidget {
31
45
  background: black;
32
46
  }
33
47
 
34
- NavPane {
35
- height: 9fr;
36
- padding: 0 2;
37
- border: round #0c323e;
38
- background: black; }
39
-
40
48
  RadioButton {
41
49
  color: #31b8e6; }
42
50
 
43
51
  Select {
44
52
  width: 20; }
45
53
 
46
- TopBar {
47
- height: 3;
48
- padding: 0 2;
49
- border: round #0c323e;
50
- dock: top;
51
- background: black }
52
-
53
54
  MarkdownViewer {
54
55
  background: black; }
55
56
 
@@ -79,8 +80,8 @@ Tree {
79
80
  .form_1 {
80
81
  padding: 0 2;
81
82
  color: #31b8e6;
82
- border: round #0c323e;
83
- border-subtitle-color: #31b8e6;
83
+ border: round #2aa5ce;
84
+ border-subtitle-color: #64e631;
84
85
  border-subtitle-style: bold;
85
86
  width: 100%;
86
87
  height: 3;
@@ -89,8 +90,8 @@ Tree {
89
90
  .form_2 {
90
91
  padding: 0 2;
91
92
  color: #31b8e6;
92
- border: round #0c323e;
93
- border-subtitle-color: #31b8e6;
93
+ border: round #2aa5ce;
94
+ border-subtitle-color: #64e631;
94
95
  border-subtitle-style: bold;
95
96
  width: 100%;
96
97
  height: 4;
@@ -99,9 +100,9 @@ Tree {
99
100
  .form_3 {
100
101
  padding: 0 2;
101
102
  color: #31b8e6;
102
- border-subtitle-color: #31b8e6;
103
+ border-subtitle-color: #64e631;
103
104
  border-subtitle-style: bold;
104
- border: round #0c323e;
105
+ border: round #2aa5ce;
105
106
  width: 100%;
106
107
  height: 5;
107
108
  background: black; }
@@ -109,8 +110,8 @@ Tree {
109
110
  .form_4 {
110
111
  padding: 0 2;
111
112
  color: #31b8e6;
112
- border: round #0c323e;
113
- border-subtitle-color: #31b8e6;
113
+ border: round #2aa5ce;
114
+ border-subtitle-color: #64e631;
114
115
  border-subtitle-style: bold;
115
116
  width: 100%;
116
117
  height: 6;
@@ -119,17 +120,17 @@ Tree {
119
120
  .form_5 {
120
121
  padding: 0 2;
121
122
  color: #31b8e6;
122
- border-subtitle-color: #31b8e6;
123
+ border-subtitle-color: #64e631;
123
124
  border-subtitle-style: bold;
124
- border: round #0c323e;
125
+ border: round #2aa5ce;
125
126
  width: 100%;
126
127
  height: 7; }
127
128
 
128
129
  .form_6 {
129
130
  padding: 0 2;
130
131
  color: #31b8e6;
131
- border: round #0c323e;
132
- border-subtitle-color: #31b8e6;
132
+ border: round #2aa5ce;
133
+ border-subtitle-color: #64e631;
133
134
  border-subtitle-style: bold;
134
135
  width: 100%;
135
136
  height: 8; }
@@ -137,8 +138,8 @@ Tree {
137
138
  .form_7 {
138
139
  padding: 0 2;
139
140
  color: #31b8e6;
140
- border: round #0c323e;
141
- border-subtitle-color: #31b8e6;
141
+ border: round #2aa5ce;
142
+ border-subtitle-color: #64e631;
142
143
  border-subtitle-style: bold;
143
144
  width: 100%;
144
145
  height: 9; }
@@ -146,8 +147,8 @@ Tree {
146
147
  .form_8 {
147
148
  padding: 0 2;
148
149
  color: #31b8e6;
149
- border: round #0c323e;
150
- border-subtitle-color: #31b8e6;
150
+ border: round #2aa5ce;
151
+ border-subtitle-color: #64e631;
151
152
  border-subtitle-style: bold;
152
153
  width: 100%;
153
154
  height: 10; }
@@ -155,15 +156,15 @@ Tree {
155
156
  .form_16 {
156
157
  padding: 0 2;
157
158
  color: #31b8e6;
158
- border: round #0c323e;
159
- border-subtitle-color: #31b8e6;
159
+ border: round #2aa5ce;
160
+ border-subtitle-color: #64e631;
160
161
  border-subtitle-style: bold;
161
162
  width: 100%;
162
163
  height: 18; }
163
164
 
164
165
  .health_box {
165
166
  color: #31b8e6;
166
- border-subtitle-color: #31b8e6;
167
+ border-subtitle-color: #64e631;
167
168
  border-subtitle-style: bold;
168
169
  }
169
170
 
@@ -171,19 +172,21 @@ Tree {
171
172
  .info_msg {
172
173
  padding: 0 2;
173
174
  color: #31b8e6;
174
- border: round #0c323e;
175
+ border: round #2aa5ce;
175
176
  width: 100%;
176
177
  }
177
178
 
178
179
  .form_box {
179
- border: round #0c323e; }
180
+ border: round #2aa5ce;
181
+ border-subtitle-color: #64e631;
182
+ }
180
183
 
181
184
  /* Intro text at the top */
182
185
 
183
186
  .form_intro {
184
187
  color: #31b8e6;
185
188
  padding: 0 2;
186
- border: round #0c323e;
189
+ border: round #2aa5ce;
187
190
  width: 100%; }
188
191
 
189
192
 
@@ -220,25 +223,25 @@ Tree {
220
223
  background: #111111; }
221
224
 
222
225
  .form_label {
223
- color: #31b8e6;
226
+ color: #64e631;
224
227
  text-style: bold;
225
228
  padding: 0 1;
226
229
  width: 30; }
227
230
 
228
231
  .form_label_15 {
229
- color: #31b8e6;
232
+ color: #64e631;
230
233
  text-style: bold;
231
234
  padding: 0 1;
232
235
  width: 15; }
233
236
 
234
237
  .form_label_20 {
235
- color: #31b8e6;
238
+ color: #64e631;
236
239
  text-style: bold;
237
240
  padding: 0 1;
238
241
  width: 20; }
239
242
 
240
243
  .form_label_25 {
241
- color: #31b8e6;
244
+ color: #64e631;
242
245
  text-style: bold;
243
246
  padding: 0 1;
244
247
  width: 25; }
@@ -248,7 +251,8 @@ Tree {
248
251
  .health_box {
249
252
  color: #31b8e6;
250
253
  height: auto;
251
- border: round #0c323e;
254
+ border: round #2aa5ce;
255
+ border-subtitle-color: #64e631;
252
256
  padding: 0 1;
253
257
  }
254
258
 
@@ -263,14 +267,14 @@ Tree {
263
267
 
264
268
  .pane_box {
265
269
  color: #31b8e6;
266
- border: round #0c323e;
270
+ border: round #2aa5ce;
267
271
  padding: 0 1;
268
272
  background: black;
269
273
  }
270
274
 
271
275
  .select_box {
272
276
  color: #31b8e6;
273
- border: round #0c323e;
277
+ border: round #2aa5ce;
274
278
  padding: 0 1;
275
279
  height: 3;
276
280
  background: black;
@@ -295,7 +299,7 @@ Tree {
295
299
  }
296
300
 
297
301
  .radio_set {
298
- border: round #0c323e;
302
+ border: round #2aa5ce;
299
303
  border-subtitle-color: #31b8e6;
300
304
  border-subtitle-style: bold;
301
305
  padding: 0 1;
@@ -308,7 +312,7 @@ Tree {
308
312
  padding: 0 1; }
309
313
 
310
314
  .switch {
311
- border: round #0c323e;
315
+ border: round #2aa5ce;
312
316
  padding: 0 1;
313
317
  height: 1;
314
318
  }
@@ -325,7 +329,7 @@ Tree {
325
329
 
326
330
  Button {
327
331
  align: center middle;
328
- border: round #0c323e;
332
+ border: round #2aa5ce;
329
333
  width: 15;
330
334
  background: black; }
331
335
 
@@ -405,6 +409,16 @@ Button {
405
409
  color: #c49b42ff;
406
410
  text-style: bold; }
407
411
 
412
+
413
+
414
+ /* ----------------- */
415
+ /* Button Visibility */
416
+ /* ----------------- */
417
+
418
+
419
+ /* New Screen */
420
+ /* ---------- */
421
+
408
422
  .new #analytics_button {
409
423
  display: none; }
410
424
 
@@ -426,27 +440,44 @@ Button {
426
440
  .new #update_button {
427
441
  display: none; }
428
442
 
429
- .update #new_button {
430
- display: none; }
431
-
432
443
  .new #delete_button {
433
444
  display: none; }
434
445
 
435
446
  .new #view_log_button {
436
447
  display: none; }
437
448
 
438
- .disabled #disable_button {
449
+
450
+ /* Element is stopped */
451
+ /* ------------------ */
452
+
453
+ .is_stopped #restart_button {
439
454
  display: none; }
440
455
 
441
- .enabled #enable_button {
456
+ .is_stopped #stop_button {
442
457
  display: none; }
443
458
 
444
- .stopped #start_button {
459
+
460
+ /* Element is running */
461
+ /* ------------------ */
462
+
463
+ .is_running #start_button {
445
464
  display: none; }
446
465
 
447
- .stopped #stop_button {
466
+ .is_running #enable_button {
448
467
  display: none; }
449
468
 
450
469
 
451
470
 
471
+ /* Uptream is not defined */
472
+ /* ---------------------- */
473
+
474
+ .no_upstream #start_button {
475
+ display: none; }
476
+
477
+ .no_upstream #stop_button {
478
+ display: none; }
479
+
480
+ .no_upstream #restart_button {
481
+ display: none; }
482
+
452
483
 
@@ -37,14 +37,14 @@ from db4e.mgr.InstallMgr import InstallMgr
37
37
  from db4e.mgr.RouteMgr import RouteMgr
38
38
  from db4e.mgr.PaneMgr import PaneMgr
39
39
  from db4e.mgr.BootstrapMgr import BootstrapMgr
40
-
41
40
  from db4e.sync.SyncClient import SyncClient
42
-
43
41
  from db4e.db.SQLDb import SQLDb
44
42
  from db4e.db.DeplDb import DeplDb
45
43
  from db4e.db.MiningDb import MiningDb
46
44
  from db4e.db.OpsDb import OpsDb
47
45
  from db4e.db.OpsETL import OpsETL
46
+ from db4e.db.HealthDb import HealthDb
47
+ from db4e.client.HealthClient import HealthClient
48
48
 
49
49
  from db4e.util.PaneCatalogue import PaneCatalogue
50
50
 
@@ -91,9 +91,11 @@ class Db4EClient(App):
91
91
  self.ops_etl = OpsETL(ops_db=self.ops_db)
92
92
  self.depl_db = DeplDb(sql_db=self.sql_db)
93
93
  self.mining_db = MiningDb(sql_db=self.sql_db)
94
+ self.health_db = HealthDb(sql_db=self.sql_db)
95
+ self.health_client = HealthClient(health_db=self.health_db)
94
96
  install_mgr = InstallMgr(bs_mgr=self.bs_mgr)
95
97
  self.pane_mgr = PaneMgr(catalogue=PaneCatalogue())
96
- self.nav_pane = NavPane(depl_db=self.depl_db)
98
+ self.nav_pane = NavPane(depl_db=self.depl_db, health_client=self.health_client)
97
99
  self.sync_client = SyncClient(
98
100
  sql_db=self.sql_db,
99
101
  ops_db=self.ops_db,
@@ -101,12 +103,13 @@ class Db4EClient(App):
101
103
  bs_mgr=self.bs_mgr,
102
104
  server_url=f"http://{DDef.ANY_IP}:{DDef.API_PORT}",
103
105
  )
104
- self.msg_router = RouteMgr(
106
+ self.route_mgr = RouteMgr(
105
107
  depl_db=self.depl_db,
106
108
  ops_db=self.ops_db,
107
109
  install_mgr=install_mgr,
108
110
  pane_mgr=self.pane_mgr,
109
111
  sync_client=self.sync_client,
112
+ health_client=self.health_client,
110
113
  )
111
114
 
112
115
  def compose(self):
@@ -134,18 +137,18 @@ class Db4EClient(App):
134
137
 
135
138
  # Every form sends the form data here
136
139
  @work(exclusive=True)
137
- async def on_db4e_msg(self, message: Db4EMsg) -> None:
140
+ async def on_db4emsg(self, message: Db4EMsg) -> None:
138
141
  # print(f"Db4EApp:on_db4e_msg(): form_data: {message.form_data}")
139
- data, pane = await self.msg_router.dispatch(
142
+ data, pane = await self.route_mgr.dispatch(
140
143
  message.form_data[DField.TO_MODULE],
141
144
  message.form_data[DField.TO_METHOD],
142
145
  message.form_data,
143
146
  )
144
- # The Db4E database is within the deployment directory that's only defined
145
- # after a successful install. The results of the "InitialInstall" are put
146
- # into the tui_log_line table and the TUI Log Pane is displayed. We
147
- # intercept that call and initialize the client database when the
148
- # "InitialInstall" is successful.
147
+ # The Db4E database is within the deployment directory that's only
148
+ # defined after a successful install. The results of the
149
+ # "InitialInstall" are put into the tui_log_line table and the TUI Log
150
+ # Pane is displayed. We intercept that call and initialize the client
151
+ # database when the "InitialInstall" is successful.
149
152
  if (
150
153
  pane == DPane.TUI_LOG
151
154
  and type(data) == list
@@ -156,6 +159,7 @@ class Db4EClient(App):
156
159
  self.ops_db.initialize()
157
160
  self.depl_db.initialize()
158
161
  self.mining_db.initialize()
162
+ self.health_db.initialize()
159
163
  self.pane_mgr.set_pane(name=pane, data=data[:-1])
160
164
  else:
161
165
  self.pane_mgr.set_pane(name=pane, data=data)
@@ -16,6 +16,7 @@ from importlib import metadata
16
16
  import subprocess
17
17
  import signal
18
18
  import re
19
+ import traceback
19
20
 
20
21
  try:
21
22
  __package_name__ = metadata.metadata(__package__ or __name__)["Name"]
@@ -27,6 +28,7 @@ except Exception:
27
28
  from db4e.mgr.BootstrapMgr import BootstrapMgr
28
29
  from db4e.mgr.DeplMgr import DeplMgr
29
30
  from db4e.mgr.APIMgr import APIMgr
31
+ from db4e.mgr.HealthMgr import HealthMgr
30
32
 
31
33
  from db4e.sync.SyncServer import init_sync_server
32
34
 
@@ -46,7 +48,7 @@ from db4e.db.SQLDb import SQLDb
46
48
  from db4e.db.DeplDb import DeplDb
47
49
  from db4e.db.MiningDb import MiningDb
48
50
  from db4e.db.OpsDb import OpsDb
49
-
51
+ from db4e.db.HealthDb import HealthDb
50
52
 
51
53
  from db4e.constants.DDebug import DDebug
52
54
  from db4e.constants.DDef import DDef
@@ -57,8 +59,6 @@ from db4e.constants.DFile import DFile
57
59
  from db4e.constants.DModule import DModule
58
60
 
59
61
 
60
- DDebug.FUNCTION = False
61
-
62
62
  POLL_INTERVAL = 5
63
63
 
64
64
 
@@ -108,6 +108,14 @@ class Db4eServer:
108
108
  sql_db=self.sql_db,
109
109
  )
110
110
 
111
+ # Health DB module
112
+ self.health_db = HealthDb(
113
+ sql_db=self.sql_db,
114
+ log_file=fq_log_file,
115
+ )
116
+ # Health manager
117
+ self.health_mgr = HealthMgr(health_db=self.health_db, log_file=fq_log_file)
118
+
111
119
  # systemd wrapper
112
120
  self.systemd = Db4ESystemD(ops_db=self.ops_db)
113
121
 
@@ -149,7 +157,7 @@ class Db4eServer:
149
157
  while True:
150
158
 
151
159
  depls = self.depl_db.get_deployments()
152
- self.log.debug(f"Db4eServer:check_deployments(): {depls}")
160
+ # self.log.debug(f"Db4eServer:check_deployments(): {depls}")
153
161
  found_primary = False
154
162
  for elem in depls:
155
163
  # Get the deployment type
@@ -211,7 +219,7 @@ class Db4eServer:
211
219
  pass
212
220
  self.log_watchers.pop((elem_type, elem.instance()), None)
213
221
 
214
- # There are no primary Monery deployments
222
+ # There are no primary Monero deployments
215
223
  if not found_primary:
216
224
  self.unset_int_p2pool_primary()
217
225
 
@@ -222,8 +230,6 @@ class Db4eServer:
222
230
  """
223
231
  Ensure logrotate files have the correct ownership.
224
232
  """
225
- if DDebug.FUNCTION:
226
- self.log.debug("Db4eServer:chown_logrotate_files():")
227
233
  logrotate_dir = self.bs_mgr.get_dir(DDir.LOGROTATE)
228
234
  # Get a list of files in the logrotate_dir
229
235
  file_list = os.listdir(logrotate_dir)
@@ -244,8 +250,6 @@ class Db4eServer:
244
250
  :param elem: Deployment object to delete.
245
251
  :type elem: object
246
252
  """
247
- if DDebug.FUNCTION:
248
- self.log.debug(f"Db4eServer:delete(): {elem}")
249
253
  self.log.info(f"Job: Deleting {elem}")
250
254
  if type(elem) == XMRig:
251
255
  elem.enabled(False)
@@ -278,8 +282,6 @@ class Db4eServer:
278
282
  :param elem: Deployment object to disable.
279
283
  :type elem: object
280
284
  """
281
- if DDebug.FUNCTION:
282
- self.log.debug(f"Db4eServer:disable(): {elem}")
283
285
  # print(f"Db4eServer:disable(): {elem}: current: {elem.enabled()}")
284
286
  if not elem.enabled():
285
287
  return
@@ -301,9 +303,6 @@ class Db4eServer:
301
303
  :param elem: Upstream deployment object.
302
304
  :type elem: object
303
305
  """
304
- if DDebug.FUNCTION:
305
- self.log.debug(f"Db4eServer:disable_downstream(): {elem}")
306
-
307
306
  if type(elem) == MoneroD or type(elem) == MoneroDRemote:
308
307
  p2pools = self.depl_db.get_p2pools()
309
308
  for p2pool in p2pools:
@@ -345,8 +344,6 @@ class Db4eServer:
345
344
  :param elem: Deployment object to enable.
346
345
  :type elem: object
347
346
  """
348
- if DDebug.FUNCTION:
349
- self.log.debug(f"Db4eServer:enable(): {elem}")
350
347
  # print(f"Db4eServer:enable(): {elem}: current: {elem.enabled()}")
351
348
  if elem.enabled():
352
349
  return
@@ -362,8 +359,6 @@ class Db4eServer:
362
359
  :param elem: Deployment object to start if needed.
363
360
  :type elem: object
364
361
  """
365
- if DDebug.FUNCTION:
366
- self.log.debug(f"Db4eServer:ensure_running(): {elem}")
367
362
  # Check if the deployment service is running, start it if it's not
368
363
  sd = self.systemd
369
364
  if type(elem) == MoneroD:
@@ -405,8 +400,6 @@ class Db4eServer:
405
400
  :param elem: Deployment object to stop if needed.
406
401
  :type elem: object
407
402
  """
408
- if DDebug.FUNCTION:
409
- self.log.debug(f"Db4eServer:ensure_stopped(): {elem}")
410
403
  sd = self.systemd
411
404
  if type(elem) == MoneroD:
412
405
  instance = elem.instance()
@@ -452,8 +445,6 @@ class Db4eServer:
452
445
  :param elem: Deployment object to restart.
453
446
  :type elem: object
454
447
  """
455
- if DDebug.FUNCTION:
456
- self.log.debug(f"Db4eServer:restart(): {elem}")
457
448
  # Note that XMRig does not need to be restarted, it's smart enough to notice that
458
449
  # the JSON config has been updated and reload the settings
459
450
  sd = self.systemd
@@ -571,12 +562,13 @@ class Db4eServer:
571
562
  sig, lambda s=sig: asyncio.create_task(handle_shutdown())
572
563
  )
573
564
 
574
- # run all 3 forever
565
+ # run all forever
575
566
  tasks = [
576
567
  asyncio.create_task(self.run_api_server(), name="api_server"),
577
568
  asyncio.create_task(self.check_deployments(), name="check_deployments"),
578
569
  asyncio.create_task(self.rotate_logs(), name="rotate_logs"),
579
570
  asyncio.create_task(self.update_current(), name="update_current"),
571
+ asyncio.create_task(self.run_healthcheck(), name="healthcheck"),
580
572
  ]
581
573
  # main loop: just wait until stop_event is set
582
574
  await self.stop_event.wait()
@@ -585,6 +577,23 @@ class Db4eServer:
585
577
  t.cancel()
586
578
  await asyncio.gather(*tasks, return_exceptions=True)
587
579
 
580
+ async def run_healthcheck(self):
581
+ """
582
+ Run health checks on deployed components.
583
+ """
584
+ try:
585
+ while True:
586
+
587
+ depls = self.depl_db.get_deployments()
588
+ for elem in depls:
589
+ self.health_mgr.check(elem)
590
+
591
+ await asyncio.sleep(POLL_INTERVAL)
592
+
593
+ except Exception as e:
594
+ self.log.critical(f"ERROR: {e}")
595
+ self.log.critical(f"STACKTRACE: {traceback.format_exc()}")
596
+
588
597
  async def shutdown(self, signum, frame):
589
598
  """
590
599
  Shutdown the server and cleanup watchers.
@@ -734,8 +743,6 @@ class Db4eServer:
734
743
  """
735
744
  Clear the primary MoneroD for internal P2Pool instances.
736
745
  """
737
- if DDebug.FUNCTION:
738
- self.log.debug("Db4eServer:unset_int_p2pool_primary():")
739
746
  for p2pool in self.depl_db.get_p2pool_internals():
740
747
  if p2pool.parent() == DField.DISABLE:
741
748
  continue
@@ -67,7 +67,7 @@ if [ $? -ne 0 ]; then
67
67
  rm $DB4E_SUDOERS
68
68
  exit 1
69
69
  fi
70
- echo "Installed as root----$DB4E_SUDOERS"
70
+ echo "Installed----$DB4E_SUDOERS"
71
71
 
72
72
  SYSTEMD_DIR=/etc/systemd/system
73
73
 
@@ -79,7 +79,7 @@ if [ $? -ne 0 ]; then
79
79
  fi
80
80
  chown root:root $SYSTEMD_DIR/db4e.service
81
81
  chmod 0644 $SYSTEMD_DIR/db4e.service
82
- echo "Installed as root----$SYSTEMD_DIR/db4e.service"
82
+ echo "Installed----$SYSTEMD_DIR/db4e.service"
83
83
 
84
84
  # Install the Monero daemon service definition file
85
85
  mv $TMP_DIR/monerod@.service $SYSTEMD_DIR
@@ -88,8 +88,8 @@ chown root:root $SYSTEMD_DIR/monerod@.service
88
88
  chown root:root $SYSTEMD_DIR/monerod@.socket
89
89
  chmod 0644 $SYSTEMD_DIR/monerod@.service
90
90
  chmod 0644 $SYSTEMD_DIR/monerod@.socket
91
- echo "Installed as root----$SYSTEMD_DIR/monerod@.service"
92
- echo "Installed as root----$SYSTEMD_DIR/monerod@.socket)"
91
+ echo "Installed----$SYSTEMD_DIR/monerod@.service"
92
+ echo "Installed----$SYSTEMD_DIR/monerod@.socket)"
93
93
 
94
94
  # Install the P2Pool service definition file
95
95
  mv $TMP_DIR/p2pool@.service $SYSTEMD_DIR
@@ -98,23 +98,23 @@ chown root:root $SYSTEMD_DIR/p2pool@.service
98
98
  chown root:root $SYSTEMD_DIR/p2pool@.socket
99
99
  chmod 0644 $SYSTEMD_DIR/p2pool@.service
100
100
  chmod 0644 $SYSTEMD_DIR/p2pool@.socket
101
- echo "Installed as root----$SYSTEMD_DIR/p2pool@.service"
102
- echo "Installed as root----$SYSTEMD_DIR/p2pool@.socket"
101
+ echo "Installed----$SYSTEMD_DIR/p2pool@.service"
102
+ echo "Installed----$SYSTEMD_DIR/p2pool@.socket"
103
103
 
104
104
  # Install the XMRig service definition file
105
105
  mv $TMP_DIR/xmrig@.service $SYSTEMD_DIR
106
106
  chown root:root $SYSTEMD_DIR/xmrig@.service
107
107
  chmod 0644 $SYSTEMD_DIR/xmrig@.service
108
- echo "Installed as root----$SYSTEMD_DIR/xmrig@.service"
108
+ echo "Installed----$SYSTEMD_DIR/xmrig@.service"
109
109
 
110
110
  systemctl daemon-reload
111
- echo "Ran as root----systemctl daemon-reload"
111
+ echo "Run Command----systemctl daemon-reload"
112
112
  systemctl enable db4e
113
- echo "Ran as root----systemctl enable db4e"
113
+ echo "Run Command----systemctl enable db4e"
114
114
  systemctl start db4e
115
- echo "Ran as root----systemctl start db4e"
115
+ echo "Run Command----systemctl start db4e"
116
116
 
117
117
  # Set SUID bit on the xmrig binary for performance reasons
118
118
  chown root:"$DB4E_GROUP" "$VENDOR_DIR/xmrig/bin/xmrig"
119
119
  chmod 4750 "$VENDOR_DIR/xmrig/bin/xmrig"
120
- echo "Set permissions as root----$VENDOR_DIR/xmrig/bin/xmrig"
120
+ echo "Set Permissions----$VENDOR_DIR/xmrig/bin/xmrig"