db4e 0.16.0__py3-none-any.whl

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 (50) hide show
  1. db4e/App.py +168 -0
  2. db4e/Db4E.tcss +104 -0
  3. db4e/Messages/NavLeafSelected.py +21 -0
  4. db4e/Messages/RefreshNavPane.py +19 -0
  5. db4e/Messages/SubmitFormData.py +19 -0
  6. db4e/Messages/SwitchPane.py +21 -0
  7. db4e/Messages/UpdateTopBar.py +20 -0
  8. db4e/Modules/ConfigMgr.py +112 -0
  9. db4e/Modules/DbMgr.py +94 -0
  10. db4e/Modules/DeploymentMgr.py +74 -0
  11. db4e/Modules/InstallMgr.py +272 -0
  12. db4e/Modules/PaneCatalogue.py +37 -0
  13. db4e/Modules/PaneMgr.py +67 -0
  14. db4e/Modules/__init__.py +0 -0
  15. db4e/Panes/Db4E.py +73 -0
  16. db4e/Panes/InitialSetup.py +70 -0
  17. db4e/Panes/InstallResults.py +36 -0
  18. db4e/Panes/Welcome.py +20 -0
  19. db4e/Templates/__init__.py +0 -0
  20. db4e/Templates/db/Deployment.py +122 -0
  21. db4e/Templates/db4e/systemd/db4e.service +18 -0
  22. db4e/Templates/monerod-0.18.4.0/bin/monerod +0 -0
  23. db4e/Templates/monerod-0.18.4.0/bin/start-monerod.sh +64 -0
  24. db4e/Templates/monerod-0.18.4.0/conf/monerod.ini +34 -0
  25. db4e/Templates/monerod-0.18.4.0/systemd/monerod@.service +21 -0
  26. db4e/Templates/monerod-0.18.4.0/systemd/monerod@.socket +13 -0
  27. db4e/Templates/p2pool-4.8/bin/p2pool +0 -0
  28. db4e/Templates/p2pool-4.8/bin/start-p2pool.sh +67 -0
  29. db4e/Templates/p2pool-4.8/conf/p2pool.ini +24 -0
  30. db4e/Templates/p2pool-4.8/systemd/p2pool@.service +19 -0
  31. db4e/Templates/p2pool-4.8/systemd/p2pool@.socket +12 -0
  32. db4e/Templates/xmrig-6.23.0/bin/xmrig +0 -0
  33. db4e/Templates/xmrig-6.23.0/conf/config.json +133 -0
  34. db4e/Templates/xmrig-6.23.0/systemd/xmrig@.service +18 -0
  35. db4e/Widgets/Clock.py +32 -0
  36. db4e/Widgets/DetailPane.py +38 -0
  37. db4e/Widgets/FormButton.py +21 -0
  38. db4e/Widgets/NavPane.py +58 -0
  39. db4e/Widgets/TopBar.py +45 -0
  40. db4e/Widgets/__init__.py +0 -0
  41. db4e/bin/db4e-backup.sh +90 -0
  42. db4e/bin/db4e-initial-setup.sh +85 -0
  43. db4e/bin/db4e-install-service.sh +43 -0
  44. db4e/bin/db4e-metrics.sh +47 -0
  45. db4e/bin/db4e-uninstall-service.sh +49 -0
  46. db4e-0.16.0.dist-info/LICENSE +674 -0
  47. db4e-0.16.0.dist-info/METADATA +31 -0
  48. db4e-0.16.0.dist-info/RECORD +50 -0
  49. db4e-0.16.0.dist-info/WHEEL +4 -0
  50. db4e-0.16.0.dist-info/entry_points.txt +3 -0
db4e/App.py ADDED
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # db4e/App.py
4
+
5
+ # Database 4 Everything
6
+ # Author: Nadim-Daniel Ghaznavi
7
+ # Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
8
+ # License: GPL 3.0
9
+
10
+ import os
11
+ import sys
12
+ from dataclasses import dataclass, field, fields
13
+ from importlib import metadata
14
+ from textual.app import App
15
+ from textual.theme import Theme as TextualTheme
16
+ from textual.widgets import Footer
17
+ from textual.containers import Vertical
18
+ from rich.theme import Theme as RichTheme
19
+ from rich.traceback import Traceback
20
+
21
+ try:
22
+ __package_name__ = metadata.metadata(__package__ or __name__)["Name"]
23
+ __version__ = metadata.version(__package__ or __name__)
24
+ except Exception:
25
+ __package_name__ = "Db4E"
26
+ __version__ = "N/A"
27
+
28
+
29
+ from db4e.Widgets.TopBar import TopBar
30
+ from db4e.Widgets.Clock import Clock
31
+ from db4e.Widgets.DetailPane import DetailPane
32
+ from db4e.Widgets.NavPane import NavPane
33
+ from db4e.Modules.ConfigMgr import ConfigMgr, Config
34
+ from db4e.Modules.DeploymentMgr import DeploymentMgr
35
+ from db4e.Modules.PaneCatalogue import PaneCatalogue
36
+ from db4e.Modules.PaneMgr import PaneMgr
37
+ from db4e.Modules.InstallMgr import InstallMgr
38
+ from db4e.Messages.SubmitFormData import SubmitFormData
39
+ from db4e.Messages.SwitchPane import SwitchPane
40
+ from db4e.Messages.UpdateTopBar import UpdateTopBar
41
+ from db4e.Messages.RefreshNavPane import RefreshNavPane
42
+ from db4e.Messages.NavLeafSelected import NavLeafSelected
43
+
44
+ RICH_THEME =RichTheme(
45
+ {
46
+ "white": "#e9e9e9",
47
+ "green": "#54efae",
48
+ "yellow": "#f6ff8f",
49
+ "dark_yellow": "#e6d733",
50
+ "red": "#fd8383",
51
+ "purple": "#b565f3",
52
+ "dark_gray": "#969aad",
53
+ "b dark_gray": "b #969aad",
54
+ "highlight": "#91abec",
55
+ "label": "#c5c7d2",
56
+ "b label": "b #c5c7d2",
57
+ "light_blue": "#bbc8e8",
58
+ "b white": "b #e9e9e9",
59
+ "b highlight": "b #91abec",
60
+ "b light_blue": "b #bbc8e8",
61
+ "recording": "#ff5e5e",
62
+ "b recording": "b #ff5e5e",
63
+ "panel_border": "#6171a6",
64
+ "table_border": "#333f62",
65
+ }
66
+ )
67
+ TEXTUAL_THEME = TextualTheme(
68
+ name="custom",
69
+ primary="white",
70
+ variables={
71
+ "white": "#e9e9e9",
72
+ "green": "#54efae",
73
+ "yellow": "#f6ff8f",
74
+ "dark_yellow": "#e6d733",
75
+ "red": "#fd8383",
76
+ "purple": "#b565f3",
77
+ "dark_gray": "#969aad",
78
+ "b_dark_gray": "b #969aad",
79
+ "highlight": "#91abec",
80
+ "label": "#c5c7d2",
81
+ "b_label": "b #c5c7d2",
82
+ "light_blue": "#bbc8e8",
83
+ "b_white": "b #e9e9e9",
84
+ "b_highlight": "b #91abec",
85
+ "b_light_blue": "b #bbc8e8",
86
+ "recording": "#ff5e5e",
87
+ "b_recording": "b #ff5e5e",
88
+ "panel_border": "#6171a6",
89
+ "table_border": "#333f62",
90
+ },
91
+ )
92
+ class Db4EApp(App):
93
+ TITLE = "Db4E"
94
+ CSS_PATH = "Db4E.tcss"
95
+
96
+ def __init__(self, config: Config, **kwargs):
97
+ super().__init__(**kwargs)
98
+ self.config = config
99
+ self.depl_mgr = DeploymentMgr(config)
100
+ self.install_mgr = InstallMgr(config)
101
+ self.pane_catalogue = PaneCatalogue()
102
+ self.initialized_flag = True if self.depl_mgr.is_initialized() else False
103
+ self.pane_mgr = PaneMgr(
104
+ config=config, catalogue=self.pane_catalogue, initialized_flag=self.initialized_flag)
105
+
106
+ # Setup the themes
107
+ theme = RICH_THEME
108
+ self.console.push_theme(theme)
109
+ self.console.set_window_title(self.TITLE)
110
+ theme = TEXTUAL_THEME
111
+ self.register_theme(theme)
112
+ self.theme = "custom"
113
+
114
+ def compose(self):
115
+ self.topbar = TopBar(app_version=__version__)
116
+ yield self.topbar
117
+ yield Vertical(
118
+ NavPane(initialized=self.initialized_flag),
119
+ Clock()
120
+ )
121
+ yield self.pane_mgr
122
+
123
+ ### Message handling happens here...
124
+
125
+ # Every form sends it's data here, we need to route the messages
126
+ async def on_submit_form_data(self, message: SubmitFormData) -> None:
127
+ target_module = message.form_data['to_module']
128
+ target_method = message.form_data['to_method']
129
+
130
+ if target_module == 'InstallMgr':
131
+ if target_method == 'initial_setup':
132
+ results = await self.install_mgr.initial_setup(message.form_data)
133
+ self.pane_mgr.set_pane(name="InstallResults", data=results)
134
+
135
+ # The individual Detail panes use this to update the TopBar
136
+ async def on_update_top_bar(self, message: UpdateTopBar) -> None:
137
+ self.topbar.set_state(title=message.title, sub_title=message.sub_title )
138
+
139
+ # This is how the Detail panes is selected and loaded, including any data
140
+ async def on_switch_pane(self, message: SwitchPane) -> None:
141
+ self.pane_mgr.set_pane(message.pane_name, message.data)
142
+
143
+ # NavPane selections are routed here
144
+ async def on_nav_leaf_selected(self, message: NavLeafSelected) -> None:
145
+ category = message.parent
146
+ instance = message.leaf
147
+ print(f"Got it: {repr(category)}/{repr(instance)}")
148
+ if category == 'Deployments' and instance == 'Db4E Core':
149
+ db4e_data = self.depl_mgr.get_deployment('db4e')
150
+ print(f"db4e_data: {db4e_data}")
151
+ self.pane_mgr.set_pane(name="Db4E", data=db4e_data)
152
+
153
+ def _handle_exception(self, error: Exception) -> None:
154
+ self.bell()
155
+ self.exit(message=Traceback(show_locals=True, width=None, locals_max_length=5))
156
+
157
+ def main():
158
+ # Set environment variables for better color support
159
+ os.environ["TERM"] = "xterm-256color"
160
+ os.environ["COLORTERM"] = "truecolor"
161
+
162
+ config_manager = ConfigMgr(__version__)
163
+ config = config_manager.get_config()
164
+ app = Db4EApp(config)
165
+ app.run()
166
+
167
+ if __name__ == "__main__":
168
+ main()
db4e/Db4E.tcss ADDED
@@ -0,0 +1,104 @@
1
+ /* Root screen layout */
2
+ Screen {
3
+ layout: grid;
4
+ grid-size: 2;
5
+ grid-columns: 1fr 4fr;
6
+ grid-rows: 13fr 1fr;
7
+ grid-gutter: 0 1;
8
+ }
9
+
10
+ Clock {
11
+ height: 3;
12
+ padding: 0 2;
13
+ border: round;
14
+ align: center middle;
15
+ background: black;
16
+ }
17
+
18
+ DetailPane {
19
+ height: 1fr;
20
+ padding: 0 2;
21
+ border: round;
22
+ row-span: 2;
23
+ background: black;
24
+ }
25
+
26
+ Db4E,
27
+ Welcome,
28
+ InstallResults {
29
+ padding: 0 2;
30
+ border: round;
31
+ background: black;
32
+ }
33
+
34
+ NavPane {
35
+ height: 9fr;
36
+ padding: 0 2;
37
+ border: round;
38
+ background: black;
39
+ }
40
+
41
+ TopBar {
42
+ height: 3;
43
+ padding: 0 2;
44
+ border: round;
45
+ dock: top;
46
+ background: black
47
+ }
48
+
49
+ #labeled_input_label {
50
+ align: right middle;
51
+ height: 1;
52
+ width: 25;
53
+ }
54
+
55
+ #topbar_title {
56
+ content-align: center middle;
57
+ width: 100%;
58
+ }
59
+
60
+ #tree_deployments {
61
+ height: auto;
62
+ }
63
+
64
+ #tree_metrics {
65
+ height: auto;
66
+ }
67
+
68
+ #initial_setup_form {
69
+ height: 5;
70
+ border: round;
71
+ }
72
+ #initial_setup_db4e_group_label {
73
+ padding: 0 1;
74
+ width: 23;
75
+ }
76
+ #initial_setup_vendor_dir_label {
77
+ padding: 0 1;
78
+ width: 23;
79
+ }
80
+ #initial_setup_user_wallet_label {
81
+ padding: 0 1;
82
+ width: 23;
83
+ }
84
+ #initial_setup_db4e_group_input {
85
+ width: 10;
86
+ }
87
+ #initial_setup_vendor_dir_input {
88
+ width: 30;
89
+ }
90
+ #initial_setup_user_wallet_input {
91
+ width: 75;
92
+ }
93
+
94
+ .form_intro {
95
+ border: round;
96
+ }
97
+
98
+ Button {
99
+ align: center middle;
100
+ height: 3;
101
+ border: round;
102
+ width: 20;
103
+ }
104
+
@@ -0,0 +1,21 @@
1
+ """
2
+ db4e/Messages/NavLeafSelected.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+
9
+ Usage example:
10
+ await self.post_message(NavLeafSelected(self)
11
+ """
12
+
13
+ from textual.widget import Widget
14
+ from textual.message import Message
15
+
16
+ class NavLeafSelected(Message):
17
+ def __init__(self, sender: Widget, parent: str, leaf: str) -> None:
18
+ super().__init__()
19
+ self.sender = sender
20
+ self.leaf = str(leaf)
21
+ self.parent = str(parent)
@@ -0,0 +1,19 @@
1
+ """
2
+ db4e/Messages/RefreshNavPane.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+
9
+ Usage example:
10
+ await self.post_message(RefreshNavPane(self)
11
+ """
12
+
13
+ from textual.widget import Widget
14
+ from textual.message import Message
15
+
16
+ class RefreshNavPane(Message):
17
+ def __init__(self, sender: Widget) -> None:
18
+ super().__init__()
19
+ self.sender = sender
@@ -0,0 +1,19 @@
1
+ """
2
+ db4e/Messages/SubmitFormData.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+
9
+ Usage example:
10
+ await self.post_message(SubmitFormData(self, resultData))
11
+ """
12
+
13
+ from textual.widget import Widget
14
+ from textual.message import Message
15
+
16
+ class SubmitFormData(Message):
17
+ def __init__(self, sender: Widget, form_data: dict) -> None:
18
+ super().__init__()
19
+ self.form_data = form_data
@@ -0,0 +1,21 @@
1
+ """
2
+ db4e/Messages/SwitchPane.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+
9
+ Usage example:
10
+ await self.post_message(SwitchPane(self, "InstallResults", results))
11
+ """
12
+
13
+ from textual.widget import Widget
14
+ from textual.message import Message
15
+
16
+ class SwitchPane(Message):
17
+ def __init__(self, sender: Widget, pane_name: str, data: dict = None):
18
+ super().__init__()
19
+ self.pane_name = str(pane_name)
20
+ self.data = data
21
+
@@ -0,0 +1,20 @@
1
+ """
2
+ db4e/Messages/UpdateTopBar.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+
9
+ Usage example:
10
+ await self.post_message(UpdateTopBar(self, "Database 4 Everything ", "Welcome"))
11
+ """
12
+
13
+ from textual.widget import Widget
14
+ from textual.message import Message
15
+
16
+ class UpdateTopBar(Message):
17
+ def __init__(self, sender: Widget, title: str, sub_title: str) -> None:
18
+ super().__init__()
19
+ self.title = title
20
+ self.sub_title = sub_title
@@ -0,0 +1,112 @@
1
+ """
2
+ db4e/Modules/ConfigManager.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+ """
9
+
10
+ import sys
11
+ import argparse
12
+
13
+ class ConfigMgr:
14
+ def __init__(self, app_version: str):
15
+ parser = argparse.ArgumentParser(description="Db4E command line switches")
16
+ parser.add_argument("-b", "--backup", action="store_true", help="Perform a db4e backup.")
17
+ parser.add_argument("-s", "--service", action="store_true", help="Run db4e as a service.")
18
+ parser.add_argument("-v", "--version", action="store_true", help="Print the db4e version.")
19
+ args = parser.parse_args()
20
+
21
+ ini = Config(app_version=app_version)
22
+ if args.backup:
23
+ ini.config['db4e']['op'] = 'run_backup'
24
+ elif args.service:
25
+ ini.config['db4e']['op'] = 'run_daemon'
26
+ elif args.version:
27
+ print(f'Db4e v{app_version}')
28
+ sys.exit(0)
29
+ else:
30
+ ini.config['db4e']['op'] = 'run_ui'
31
+ self.ini = ini
32
+
33
+ def get_config(self):
34
+ return self.ini
35
+
36
+ class Config:
37
+ def __init__(self, app_version: str):
38
+ self.config = {
39
+ 'db4e': {
40
+ 'app_version': app_version,
41
+ 'op': 'run_ui',
42
+ 'api_dir': 'api',
43
+ 'bin_dir': 'bin',
44
+ 'conf_dir': 'conf',
45
+ 'db4e_dir': 'db4e',
46
+ 'desc': 'Database 4 Everything',
47
+ 'dev_dir': 'dev',
48
+ 'log_dir': 'logs',
49
+ 'process': 'db4e.sh',
50
+ 'pypi_repository': 'https://pypi.org/pypi/db4e/json',
51
+ 'refresh_interval': 15,
52
+ 'run_dir': 'run',
53
+ 'service_file': 'db4e.service',
54
+ 'setup_script': 'db4e-initial-setup.sh',
55
+ 'service_install_script': 'db4e-install-service.sh',
56
+ 'service_log_file': 'db4e.log',
57
+ 'service_uninstaller': 'db4e-uninstall-service.sh',
58
+ 'src_dir': 'src',
59
+ 'systemd_dir': 'systemd',
60
+ 'template_dir': 'Templates',
61
+ 'vendor_dir': 'vendor',
62
+ },
63
+ 'db': {
64
+ 'backup_dir': 'backups',
65
+ 'backup_script':'db4e-backup.sh',
66
+ 'collection': 'mining',
67
+ 'depl_collection': 'depl',
68
+ 'log_collection': 'logging',
69
+ # How many days of data to keep in the logging collection
70
+ 'log_retention_days': 7,
71
+ 'max_backups': 7,
72
+ 'metrics_collection': 'metrics',
73
+ 'name': 'db4e',
74
+ 'port': 27017,
75
+ 'retry_timeout': 15,
76
+ 'server': 'localhost',
77
+ },
78
+ 'monerod': {
79
+ 'blockchain_dir': 'monero-blockchain',
80
+ 'config': 'monerod.ini',
81
+ 'desc': 'Monero Blockchain Daemon',
82
+ 'log_file': 'monerod.log',
83
+ 'process': 'monerod',
84
+ 'service_file': 'monerod@.service',
85
+ 'socket_file': 'monerod@.socket',
86
+ 'stdin_pipe': 'monerod.stdin',
87
+ 'start_script': 'start-monerod.sh',
88
+ 'version': '0.18.4.0',
89
+ },
90
+ 'p2pool': {
91
+ 'config': 'p2pool.ini',
92
+ 'desc': 'P2Pool Daemon',
93
+ 'log_file': 'p2pool.log',
94
+ 'process': 'p2pool',
95
+ 'service_file': 'p2pool@.service',
96
+ 'socket_file': 'p2pool@.socket',
97
+ 'start_script': 'start-p2pool.sh',
98
+ 'stdin': 'p2pool.stdin',
99
+ 'version': '4.8',
100
+ },
101
+ 'xmrig': {
102
+ 'desc': 'XMRig Miner',
103
+ 'conf_dir': 'conf',
104
+ 'config': 'config.json',
105
+ 'permissions': '-rwsr-x---',
106
+ 'process': 'xmrig',
107
+ 'service_file': 'xmrig@.service',
108
+ 'version': '6.23.0',
109
+ }
110
+ }
111
+
112
+
db4e/Modules/DbMgr.py ADDED
@@ -0,0 +1,94 @@
1
+ """
2
+ db4e/Modules/DbManager.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+ """
9
+
10
+ import time
11
+ from pymongo import MongoClient
12
+ from pymongo.errors import ConnectionFailure, CollectionInvalid
13
+
14
+ from db4e.Modules.ConfigMgr import Config
15
+ from db4e.Templates.db.Deployment import DB4E_RECORD
16
+
17
+ class DbMgr:
18
+
19
+ def __init__(self, config: Config):
20
+ self.ini = config
21
+ # MongoDB settings
22
+ retry_timeout = self.ini.config['db']['retry_timeout']
23
+ db_server = self.ini.config['db']['server']
24
+ db_port = self.ini.config['db']['port']
25
+ self.max_backups = self.ini.config['db']['max_backups']
26
+ self.db_name = self.ini.config['db']['name']
27
+ self.db_collection = self.ini.config['db']['collection']
28
+ self.depl_collection = self.ini.config['db']['depl_collection']
29
+ self.log_collection = self.ini.config['db']['log_collection']
30
+ self.log_retention = self.ini.config['db']['log_retention_days']
31
+ self.metrics_collection = self.ini.config['db']['metrics_collection']
32
+ # TODO Setup logging
33
+ #self.log = Db4eLogger('Db4eDb')
34
+
35
+ # Connect to MongoDB
36
+ db_uri = f'mongodb://{db_server}:{db_port}'
37
+ try:
38
+ self._client = MongoClient(db_uri)
39
+ except ConnectionFailure as e:
40
+ # TODO factor in the old Db4eLogger code....
41
+ #self.log.critical(f'Connection failed: {e}. Retrying in {retry_timeout} seconds...')
42
+ time.sleep(retry_timeout)
43
+
44
+ self.db4e = self._client[self.db_name]
45
+
46
+ # Used for backups
47
+ self.db4e_dir = None
48
+ self.repo_dir = None
49
+ self.init_db()
50
+
51
+ def ensure_indexes(self):
52
+ log_col = self.get_collection(self.log_collection)
53
+ if "timestamp_1" not in log_col.index_information():
54
+ log_col.create_index("timestamp")
55
+ # TODO self.log.debug("Created index on 'timestamp' for log collection.")
56
+
57
+ def find_one(self, col_name, filter):
58
+ col = self.get_collection(col_name)
59
+ return col.find_one(filter)
60
+
61
+ def get_collection(self, col_name):
62
+ return self.db4e[col_name]
63
+
64
+ def get_new_rec(self, rec_type):
65
+ if rec_type == 'db4e':
66
+ return DB4E_RECORD
67
+
68
+ def init_db(self):
69
+ # Make sure the 'db4e' database, core collections and indexes exist.
70
+ db_col = self.db_collection
71
+ log_col = self.log_collection
72
+ depl_col = self.depl_collection
73
+ metrics_col = self.metrics_collection
74
+ db_col_names = self.db4e.list_collection_names()
75
+ for aCol in [ db_col, log_col, depl_col, metrics_col ]:
76
+ if aCol not in db_col_names:
77
+ try:
78
+ self.db4e.create_collection(aCol)
79
+ if aCol == log_col:
80
+ log_col = self.get_collection(log_col)
81
+ log_col.create_index('timestamp')
82
+ except CollectionInvalid:
83
+ # TODO self.log.warning(f"Attempted to create existing collection: {aCol}")
84
+ pass
85
+ # TODO self.log.debug(f'Created DB collection ({aCol})')
86
+ self.ensure_indexes()
87
+
88
+ def insert_one(self, col_name, jdoc):
89
+ collection = self.get_collection(col_name)
90
+ return collection.insert_one(jdoc)
91
+
92
+ def update_one(self, col_name, filter, new_values):
93
+ collection = self.get_collection(col_name)
94
+ return collection.update_one(filter, {'$set' : new_values})
@@ -0,0 +1,74 @@
1
+ """
2
+ db4e/Modules/DeploymentManager.py
3
+
4
+ Database 4 Everything
5
+ Author: Nadim-Daniel Ghaznavi
6
+ Copyright (c) 2024-2025 NadimGhaznavi <https://github.com/NadimGhaznavi/db4e>
7
+ License: GPL 3.0
8
+ """
9
+
10
+ import os, shutil
11
+ from datetime import datetime, timezone
12
+ import getpass
13
+
14
+ from db4e.Modules.ConfigMgr import Config
15
+ from db4e.Modules.DbMgr import DbMgr
16
+
17
+ # The Mongo collection that houses the deployment records
18
+ DEPL_COL = 'depl'
19
+
20
+ class DeploymentMgr:
21
+
22
+ def __init__(self, config: Config):
23
+ self.ini = config
24
+ self.db = DbMgr(config)
25
+ self.col_name = DEPL_COL
26
+
27
+ def add_deployment(self, rec):
28
+ rec['doc_type'] = 'deployment'
29
+ rec['updated'] = datetime.now(timezone.utc)
30
+ # Get the component version from the static YAML config file
31
+ if rec['component'] == 'db4e':
32
+ rec['user'] = getpass.getuser()
33
+ else:
34
+ rec['version'] = self.ini.config[rec['component']]['version']
35
+ self.db.insert_one(self.col_name, rec)
36
+
37
+ def is_initialized(self):
38
+ rec = self.db.find_one(self.col_name, {'doc_type': 'deployment', 'component': 'db4e'})
39
+ if rec:
40
+ return True
41
+ else:
42
+ return False
43
+
44
+ def get_deployment(self, component):
45
+ print(f"DeploymentMgr:get_deployment(): {component}")
46
+ # Ask the db for the component record
47
+ db_rec = self.db.find_one(self.col_name, {'doc_type': 'deployment', 'component': component})
48
+ # rec is a cursor object.
49
+ if db_rec:
50
+ rec = {}
51
+ component = db_rec['component']
52
+ if component == 'db4e':
53
+ rec['group'] = db_rec['group']
54
+ rec['install_dir'] = db_rec['install_dir']
55
+ rec['user'] = db_rec['user']
56
+ rec['user_wallet'] = db_rec['user_wallet']
57
+ rec['vendor_dir'] = db_rec['vendor_dir']
58
+ return rec
59
+ # No record for this deployment exists
60
+
61
+ # Check if this is the first time the app has been run
62
+ rec = self.db.find_one(self.col_name, {'doc_type': 'deployment', 'component': 'db4e'})
63
+ if not rec:
64
+ return False
65
+
66
+ def get_deployment_by_instance(self, component, instance):
67
+ if instance == 'db4e core':
68
+ return self.get_deployment('db4e')
69
+
70
+ def update_deployent(self, rec):
71
+ component = rec['component']
72
+ if component == 'db4e':
73
+ filter = {'doc_type': 'deployment', 'component': 'db4e'}
74
+ self.db.update_one(self.col_name, filter, rec)