primitive 0.2.10__py3-none-any.whl → 0.2.11__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.
- primitive/__about__.py +1 -1
- primitive/agent/actions.py +20 -18
- primitive/agent/runner.py +30 -33
- primitive/cli.py +2 -0
- primitive/client.py +41 -16
- primitive/daemons/actions.py +48 -62
- primitive/daemons/commands.py +68 -22
- primitive/daemons/launch_agents.py +205 -122
- primitive/daemons/launch_service.py +224 -164
- primitive/daemons/ui.py +41 -0
- primitive/db/base.py +5 -0
- primitive/db/models.py +78 -0
- primitive/db/sqlite.py +27 -0
- primitive/exec/actions.py +0 -1
- primitive/files/actions.py +0 -1
- primitive/hardware/actions.py +4 -8
- primitive/hardware/commands.py +1 -68
- primitive/hardware/ui.py +67 -0
- primitive/monitor/actions.py +102 -0
- primitive/monitor/commands.py +13 -0
- primitive/reservations/actions.py +0 -2
- primitive/utils/auth.py +0 -2
- primitive/utils/daemons.py +54 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/METADATA +3 -1
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/RECORD +28 -20
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/WHEEL +0 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/entry_points.txt +0 -0
- {primitive-0.2.10.dist-info → primitive-0.2.11.dist-info}/licenses/LICENSE.txt +0 -0
@@ -2,178 +2,238 @@ import os
|
|
2
2
|
import configparser
|
3
3
|
import subprocess
|
4
4
|
from pathlib import Path
|
5
|
+
from loguru import logger
|
6
|
+
from ..utils.daemons import Daemon
|
5
7
|
|
6
8
|
HOME_DIRECTORY = Path.home()
|
7
|
-
|
8
9
|
PRIMITIVE_BINARY_PATH = Path(HOME_DIRECTORY / ".pyenv" / "shims" / "primitive")
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
15
|
-
|
16
|
-
|
17
|
-
)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
11
|
+
|
12
|
+
class LaunchService(Daemon):
|
13
|
+
def __init__(self, label: str):
|
14
|
+
self.label = label
|
15
|
+
self.name = label.split(".")[-1]
|
16
|
+
|
17
|
+
@property
|
18
|
+
def service_name(self) -> str:
|
19
|
+
return f"{self.label}.service"
|
20
|
+
|
21
|
+
@property
|
22
|
+
def file_path(self) -> Path:
|
23
|
+
return Path(HOME_DIRECTORY / ".config" / "systemd" / "user" / self.service_name)
|
24
|
+
|
25
|
+
@property
|
26
|
+
def logs(self) -> Path:
|
27
|
+
return Path(HOME_DIRECTORY / ".cache" / "primitive" / f"{self.label}.log")
|
28
|
+
|
29
|
+
def stop(self) -> bool:
|
30
|
+
try:
|
31
|
+
if self.is_active():
|
32
|
+
stop_existing_service = f"systemctl --user stop {self.service_name}"
|
33
|
+
subprocess.check_output(
|
34
|
+
stop_existing_service.split(" "), stderr=subprocess.DEVNULL
|
35
|
+
)
|
36
|
+
logger.info(f":white_check_mark: {self.label} stopped successfully!")
|
37
|
+
return True
|
38
|
+
except subprocess.CalledProcessError as exception:
|
39
|
+
if exception.returncode == 4:
|
40
|
+
logger.debug(f"{self.label} is not running or does not exist.")
|
41
|
+
return True
|
42
|
+
else:
|
43
|
+
logger.error(f"Unable to stop {self.label}, {exception.returncode}")
|
44
|
+
logger.error(exception)
|
45
|
+
return False
|
46
|
+
|
47
|
+
def start(self) -> bool:
|
48
|
+
try:
|
49
|
+
start_new_service = f"systemctl --user start {self.service_name}"
|
50
|
+
subprocess.check_output(start_new_service.split(" "))
|
51
|
+
logger.info(f":white_check_mark: {self.label} started successfully!")
|
52
|
+
return True
|
53
|
+
except subprocess.CalledProcessError as exception:
|
54
|
+
logger.error(f"Unable to start {self.label}")
|
55
|
+
logger.error(exception)
|
56
|
+
return False
|
57
|
+
|
58
|
+
def disable(self) -> bool:
|
59
|
+
try:
|
60
|
+
if self.is_installed():
|
61
|
+
disable_existing_service = (
|
62
|
+
f"systemctl --user disable {self.service_name}"
|
63
|
+
)
|
64
|
+
subprocess.check_output(
|
65
|
+
disable_existing_service.split(" "), stderr=subprocess.DEVNULL
|
66
|
+
)
|
67
|
+
return True
|
68
|
+
except subprocess.CalledProcessError as exception:
|
69
|
+
logger.error(f"Unable to disable {self.label}")
|
70
|
+
logger.error(exception)
|
71
|
+
return False
|
72
|
+
|
73
|
+
def enable(self) -> bool:
|
74
|
+
try:
|
75
|
+
enable_service = f"systemctl --user enable {self.service_name}"
|
76
|
+
subprocess.check_output(
|
77
|
+
enable_service.split(" "), stderr=subprocess.DEVNULL
|
78
|
+
)
|
79
|
+
return True
|
80
|
+
except subprocess.CalledProcessError as exception:
|
81
|
+
logger.error(f"Unable to enable {self.label}")
|
82
|
+
logger.error(exception)
|
83
|
+
return False
|
84
|
+
|
85
|
+
def verify(self) -> bool:
|
86
|
+
systemctl_check = (
|
87
|
+
f"systemctl --user show {self.service_name} -p CanStart --value"
|
35
88
|
)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
89
|
+
try:
|
90
|
+
output = (
|
91
|
+
subprocess.check_output(systemctl_check.split(" ")).decode().strip()
|
92
|
+
)
|
93
|
+
if output == "no":
|
94
|
+
raise Exception(f"{systemctl_check} yielded {output}")
|
95
|
+
return True
|
96
|
+
except subprocess.CalledProcessError as exception:
|
97
|
+
logger.error(f"Unable to verify {self.label}")
|
98
|
+
logger.error(exception)
|
99
|
+
return False
|
100
|
+
|
101
|
+
def view_logs(self) -> None:
|
102
|
+
follow_logs = f"tail -f -n +1 {self.logs}"
|
103
|
+
os.system(follow_logs)
|
104
|
+
|
105
|
+
def populate(self) -> bool:
|
106
|
+
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
107
|
+
self.file_path.touch()
|
108
|
+
|
109
|
+
if self.file_path.exists():
|
110
|
+
self.file_path.unlink()
|
111
|
+
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
112
|
+
self.file_path.touch()
|
113
|
+
|
114
|
+
config = configparser.ConfigParser()
|
115
|
+
config.optionxform = str # type: ignore
|
116
|
+
|
117
|
+
config["Unit"] = {
|
118
|
+
"Description": "Primitive Agent",
|
119
|
+
"After": "network.target",
|
120
|
+
}
|
121
|
+
|
122
|
+
found_primitive_binary_path = PRIMITIVE_BINARY_PATH
|
123
|
+
if not PRIMITIVE_BINARY_PATH.exists():
|
124
|
+
result = subprocess.run(["which", "primitive"], capture_output=True)
|
125
|
+
if result.returncode == 0:
|
126
|
+
found_primitive_binary_path = result.stdout.decode().rstrip("\n")
|
127
|
+
else:
|
128
|
+
print("primitive binary not found")
|
129
|
+
return False
|
130
|
+
|
131
|
+
config["Service"] = {
|
132
|
+
"ExecStart": f'/bin/sh -lc "{found_primitive_binary_path} agent"',
|
133
|
+
"Restart": "always",
|
134
|
+
"StandardError": f"append:{self.logs}",
|
135
|
+
"StandardOutput": f"append:{self.logs}",
|
136
|
+
}
|
137
|
+
|
138
|
+
config["Install"] = {
|
139
|
+
"WantedBy": "default.target",
|
140
|
+
}
|
141
|
+
|
142
|
+
try:
|
143
|
+
with open(self.file_path, "w") as service_file:
|
144
|
+
config.write(service_file)
|
145
|
+
except IOError as exception:
|
146
|
+
print(f"populate_service_file: {exception}")
|
147
|
+
|
148
|
+
self.file_path.chmod(0o644)
|
149
|
+
return self.verify()
|
150
|
+
|
151
|
+
def create_stdout_file(self) -> bool:
|
152
|
+
try:
|
153
|
+
if not self.logs.exists():
|
154
|
+
self.logs.parent.mkdir(parents=True, exist_ok=True)
|
155
|
+
self.logs.touch()
|
156
|
+
|
157
|
+
return True
|
158
|
+
except Exception as e:
|
159
|
+
logger.error(
|
160
|
+
f"Unable to create log file at {self.logs} for daemon {self.label}"
|
161
|
+
)
|
162
|
+
logger.error(e)
|
163
|
+
return False
|
164
|
+
|
165
|
+
def delete_stdout_file(self) -> bool:
|
166
|
+
try:
|
167
|
+
if self.logs.exists():
|
168
|
+
self.logs.unlink()
|
169
|
+
|
170
|
+
return True
|
171
|
+
except Exception as e:
|
172
|
+
logger.error(
|
173
|
+
f"Unable to delete log file at {self.logs} for daemon {self.label}"
|
48
174
|
)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
175
|
+
logger.error(e)
|
176
|
+
return False
|
177
|
+
|
178
|
+
def delete_service_file(self) -> bool:
|
179
|
+
try:
|
180
|
+
if self.file_path.exists():
|
181
|
+
self.file_path.unlink()
|
182
|
+
|
183
|
+
return True
|
184
|
+
except Exception as e:
|
185
|
+
logger.error(
|
186
|
+
f"Unable to delete service file at {self.file_path} for daemon {self.label}"
|
187
|
+
)
|
188
|
+
logger.error(e)
|
189
|
+
return False
|
54
190
|
|
191
|
+
def install(self) -> bool:
|
192
|
+
return all(
|
193
|
+
[
|
194
|
+
self.stop(),
|
195
|
+
self.disable(),
|
196
|
+
self.populate(),
|
197
|
+
self.create_stdout_file(),
|
198
|
+
self.enable(),
|
199
|
+
self.start(),
|
200
|
+
]
|
201
|
+
)
|
55
202
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
203
|
+
def uninstall(self) -> bool:
|
204
|
+
return all(
|
205
|
+
[
|
206
|
+
self.stop(),
|
207
|
+
self.disable(),
|
208
|
+
self.delete_service_file(),
|
209
|
+
self.delete_stdout_file(),
|
210
|
+
]
|
60
211
|
)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
PRIMITIVE_AGENT_SERVICE_FILEPATH.parent.mkdir(parents=True, exist_ok=True)
|
75
|
-
PRIMITIVE_AGENT_SERVICE_FILEPATH.touch()
|
76
|
-
|
77
|
-
config = configparser.ConfigParser()
|
78
|
-
config.optionxform = str # type: ignore
|
79
|
-
|
80
|
-
config["Unit"] = {
|
81
|
-
"Description": "Primitive Agent",
|
82
|
-
"After": "network.target",
|
83
|
-
}
|
84
|
-
|
85
|
-
found_primitive_binary_path = PRIMITIVE_BINARY_PATH
|
86
|
-
if not PRIMITIVE_BINARY_PATH.exists():
|
87
|
-
result = subprocess.run(["which", "primitive"], capture_output=True)
|
88
|
-
if result.returncode == 0:
|
89
|
-
found_primitive_binary_path = result.stdout.decode().rstrip("\n")
|
90
|
-
else:
|
91
|
-
print("primitive binary not found")
|
212
|
+
|
213
|
+
def is_active(self) -> bool:
|
214
|
+
try:
|
215
|
+
is_service_active = (
|
216
|
+
f"systemctl --user show {self.service_name} -p ActiveState --value"
|
217
|
+
)
|
218
|
+
output = (
|
219
|
+
subprocess.check_output(is_service_active.split(" ")).decode().strip()
|
220
|
+
)
|
221
|
+
return output == "active"
|
222
|
+
except subprocess.CalledProcessError as exception:
|
223
|
+
logger.error(f"Unable to check if {self.label} is active")
|
224
|
+
logger.error(exception)
|
92
225
|
return False
|
93
226
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
config.write(service_file)
|
108
|
-
except IOError as exception:
|
109
|
-
print(f"populate_service_file: {exception}")
|
110
|
-
|
111
|
-
PRIMITIVE_AGENT_SERVICE_FILEPATH.chmod(0o644)
|
112
|
-
verify_service_file()
|
113
|
-
|
114
|
-
|
115
|
-
def verify_service_file():
|
116
|
-
systemctl_check = (
|
117
|
-
f"systemctl --user show {PRIMITIVE_AGENT_SERVICE} -p CanStart --value"
|
118
|
-
)
|
119
|
-
try:
|
120
|
-
output = subprocess.check_output(systemctl_check.split(" ")).decode().strip()
|
121
|
-
if output == "no":
|
122
|
-
raise Exception(f"{systemctl_check} yielded {output}")
|
123
|
-
return True
|
124
|
-
except subprocess.CalledProcessError as exception:
|
125
|
-
print("verify_service_file: ", exception)
|
126
|
-
return False
|
127
|
-
|
128
|
-
|
129
|
-
def create_stdout_file():
|
130
|
-
if not PRIMITIVE_AGENT_LOGS_FILEPATH.exists():
|
131
|
-
PRIMITIVE_AGENT_LOGS_FILEPATH.parent.mkdir(parents=True, exist_ok=True)
|
132
|
-
PRIMITIVE_AGENT_LOGS_FILEPATH.touch()
|
133
|
-
|
134
|
-
|
135
|
-
def delete_stdout_file():
|
136
|
-
if PRIMITIVE_AGENT_LOGS_FILEPATH.exists():
|
137
|
-
PRIMITIVE_AGENT_LOGS_FILEPATH.unlink()
|
138
|
-
|
139
|
-
|
140
|
-
def enable_service():
|
141
|
-
try:
|
142
|
-
enable_service = f"systemctl --user enable {PRIMITIVE_AGENT_SERVICE}"
|
143
|
-
subprocess.check_output(enable_service.split(" "))
|
144
|
-
return True
|
145
|
-
except subprocess.CalledProcessError as exception:
|
146
|
-
print("enable_service: ", exception)
|
147
|
-
return False
|
148
|
-
|
149
|
-
|
150
|
-
def start_service():
|
151
|
-
try:
|
152
|
-
start_new_service = f"systemctl --user start {PRIMITIVE_AGENT_SERVICE}"
|
153
|
-
subprocess.check_output(start_new_service.split(" "))
|
154
|
-
return True
|
155
|
-
except subprocess.CalledProcessError as exception:
|
156
|
-
print("start_service: ", exception)
|
157
|
-
return False
|
158
|
-
|
159
|
-
|
160
|
-
def view_service_logs():
|
161
|
-
follow_logs = f"tail -f -n +1 {PRIMITIVE_AGENT_LOGS_FILEPATH}"
|
162
|
-
os.system(follow_logs)
|
163
|
-
|
164
|
-
|
165
|
-
def full_service_install():
|
166
|
-
stop_service()
|
167
|
-
disable_service()
|
168
|
-
populate_service_file()
|
169
|
-
create_stdout_file()
|
170
|
-
enable_service()
|
171
|
-
start_service()
|
172
|
-
|
173
|
-
|
174
|
-
def full_service_uninstall():
|
175
|
-
stop_service()
|
176
|
-
disable_service()
|
177
|
-
if PRIMITIVE_AGENT_SERVICE_FILEPATH.exists():
|
178
|
-
PRIMITIVE_AGENT_SERVICE_FILEPATH.unlink()
|
179
|
-
delete_stdout_file()
|
227
|
+
def is_installed(self) -> bool:
|
228
|
+
try:
|
229
|
+
is_service_active = (
|
230
|
+
f"systemctl --user show {self.service_name} -p UnitFileState --value" # noqa
|
231
|
+
)
|
232
|
+
output = (
|
233
|
+
subprocess.check_output(is_service_active.split(" ")).decode().strip()
|
234
|
+
)
|
235
|
+
return output == "enabled"
|
236
|
+
except subprocess.CalledProcessError as exception:
|
237
|
+
logger.error(f"Unable to check if {self.label} is enabled")
|
238
|
+
logger.error(exception)
|
239
|
+
return False
|
primitive/daemons/ui.py
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
from rich.console import Console
|
2
|
+
from rich.table import Table
|
3
|
+
from typing import List
|
4
|
+
|
5
|
+
from ..utils.daemons import Daemon
|
6
|
+
|
7
|
+
|
8
|
+
def render_daemon_list(daemons: List[Daemon]) -> None:
|
9
|
+
console = Console()
|
10
|
+
|
11
|
+
table = Table(show_header=True, header_style="bold #FFA800")
|
12
|
+
table.add_column("Name")
|
13
|
+
table.add_column("Label")
|
14
|
+
table.add_column("Installed")
|
15
|
+
table.add_column("Active")
|
16
|
+
table.add_column("File Path")
|
17
|
+
table.add_column("Log Path")
|
18
|
+
|
19
|
+
for daemon in daemons:
|
20
|
+
child_table = Table(show_header=False, header_style="bold #FFA800")
|
21
|
+
child_table.add_column("Name")
|
22
|
+
child_table.add_column("Label")
|
23
|
+
child_table.add_column("Installed")
|
24
|
+
child_table.add_column("Active")
|
25
|
+
child_table.add_column("File Path")
|
26
|
+
child_table.add_column("Log Path")
|
27
|
+
|
28
|
+
table.add_row(
|
29
|
+
daemon.name,
|
30
|
+
daemon.label,
|
31
|
+
"[bold green]Yes[/bold green]"
|
32
|
+
if daemon.is_installed()
|
33
|
+
else "[bold red]No[/bold red]",
|
34
|
+
"[bold green]Yes[/bold green]"
|
35
|
+
if daemon.is_active()
|
36
|
+
else "[bold red]No[/bold red]",
|
37
|
+
str(daemon.file_path),
|
38
|
+
str(daemon.logs),
|
39
|
+
)
|
40
|
+
|
41
|
+
console.print(table)
|
primitive/db/base.py
ADDED
primitive/db/models.py
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
from sqlalchemy import Column, Integer, String
|
2
|
+
from sqlalchemy.orm import Mapped, mapped_column, Query
|
3
|
+
from typing import Optional, Generic, TypeVar, Callable, Type, List, Union, Dict, Any
|
4
|
+
from .sqlite import Session
|
5
|
+
from .base import Base
|
6
|
+
|
7
|
+
T = TypeVar("T", bound="Base")
|
8
|
+
|
9
|
+
|
10
|
+
class Manager(Generic[T]):
|
11
|
+
def __init__(self, model_cls_lambda: Callable[[], Type[T]]) -> None:
|
12
|
+
self.model_cls_lambda = model_cls_lambda
|
13
|
+
self.filters: Dict[str, Any] = {}
|
14
|
+
|
15
|
+
def create(self, **kwargs) -> T:
|
16
|
+
with Session() as session:
|
17
|
+
model = self.model_cls_lambda()
|
18
|
+
obj = model(**kwargs)
|
19
|
+
session.add(obj)
|
20
|
+
session.commit()
|
21
|
+
session.refresh(obj)
|
22
|
+
return obj
|
23
|
+
|
24
|
+
def filter_by(self, **kwargs) -> "Manager[T]":
|
25
|
+
self.filters = kwargs
|
26
|
+
return self
|
27
|
+
|
28
|
+
def all(self) -> List[T]:
|
29
|
+
with Session() as session:
|
30
|
+
model = self.model_cls_lambda()
|
31
|
+
query = session.query(model)
|
32
|
+
query.filter_by(**self.filters)
|
33
|
+
self.filters.clear()
|
34
|
+
return query.all()
|
35
|
+
|
36
|
+
def first(self) -> Union[T, None]:
|
37
|
+
with Session() as session:
|
38
|
+
model = self.model_cls_lambda()
|
39
|
+
query = session.query(model)
|
40
|
+
query.filter_by(**self.filters)
|
41
|
+
self.filters.clear()
|
42
|
+
return query.first()
|
43
|
+
|
44
|
+
def update(self, update: Dict[Any, Any]) -> Query[T]:
|
45
|
+
with Session() as session:
|
46
|
+
model = self.model_cls_lambda()
|
47
|
+
query = session.query(model).filter_by(**self.filters)
|
48
|
+
|
49
|
+
if query.count() > 0:
|
50
|
+
query.update(update)
|
51
|
+
session.commit()
|
52
|
+
return query
|
53
|
+
else:
|
54
|
+
raise ValueError(f"{model.__name__} not found")
|
55
|
+
|
56
|
+
def delete(self) -> None:
|
57
|
+
with Session() as session:
|
58
|
+
model = self.model_cls_lambda()
|
59
|
+
query = session.query(model).filter_by(**self.filters)
|
60
|
+
|
61
|
+
if query.count() > 0:
|
62
|
+
query.delete()
|
63
|
+
session.commit()
|
64
|
+
else:
|
65
|
+
raise ValueError(f"{model.__name__} not found")
|
66
|
+
|
67
|
+
|
68
|
+
class JobRun(Base):
|
69
|
+
__tablename__ = "JobRun"
|
70
|
+
|
71
|
+
id = Column(Integer, primary_key=True)
|
72
|
+
job_run_id: Mapped[str] = mapped_column(String, nullable=False)
|
73
|
+
pid: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
74
|
+
|
75
|
+
objects: Manager["JobRun"] = Manager(lambda: JobRun)
|
76
|
+
|
77
|
+
def __repr__(self):
|
78
|
+
return f"<JobRun(id={self.id} job_run_id={self.job_run_id}, pid={self.pid})>"
|
primitive/db/sqlite.py
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from sqlalchemy import create_engine, Engine
|
3
|
+
from sqlalchemy.orm import Session as SQLAlchemySession
|
4
|
+
from ..utils.cache import get_cache_dir
|
5
|
+
from .base import Base
|
6
|
+
|
7
|
+
|
8
|
+
def init() -> None:
|
9
|
+
db_path: Path = get_cache_dir() / "primitive.sqlite3"
|
10
|
+
|
11
|
+
# Drop DB existing database if it exists
|
12
|
+
if db_path.exists():
|
13
|
+
db_path.unlink()
|
14
|
+
|
15
|
+
engine = create_engine(f"sqlite:///{db_path}", echo=False)
|
16
|
+
Base.metadata.create_all(engine)
|
17
|
+
|
18
|
+
|
19
|
+
def engine() -> Engine:
|
20
|
+
db_path: Path = get_cache_dir() / "primitive.sqlite3"
|
21
|
+
return create_engine(f"sqlite:///{db_path}", echo=False)
|
22
|
+
|
23
|
+
|
24
|
+
def Session() -> SQLAlchemySession:
|
25
|
+
from sqlalchemy.orm import sessionmaker
|
26
|
+
|
27
|
+
return sessionmaker(bind=engine())()
|
primitive/exec/actions.py
CHANGED
@@ -58,7 +58,6 @@ class Exec(BaseAction):
|
|
58
58
|
|
59
59
|
reservation = reservation_result.data["reservation"]
|
60
60
|
if reservation.get("status") != "in_progress":
|
61
|
-
logger.enable("primitive")
|
62
61
|
logger.info(
|
63
62
|
f"Reservation {reservation.get('id')} is in status {reservation.get('status')}, cannot execute command at this time."
|
64
63
|
)
|
primitive/files/actions.py
CHANGED
primitive/hardware/actions.py
CHANGED
@@ -293,7 +293,6 @@ class Hardware(BaseAction):
|
|
293
293
|
)
|
294
294
|
if messages := result.data.get("registerHardware").get("messages"):
|
295
295
|
for message in messages:
|
296
|
-
logger.enable("primitive")
|
297
296
|
if message.get("kind") == "ERROR":
|
298
297
|
logger.error(message.get("message"))
|
299
298
|
else:
|
@@ -327,7 +326,6 @@ class Hardware(BaseAction):
|
|
327
326
|
|
328
327
|
if messages := result.data.get("unregisterHardware").get("messages"):
|
329
328
|
for message in messages:
|
330
|
-
logger.enable("primitive")
|
331
329
|
if message.get("kind") == "ERROR":
|
332
330
|
logger.error(message.get("message"))
|
333
331
|
else:
|
@@ -368,11 +366,11 @@ class Hardware(BaseAction):
|
|
368
366
|
mutation, variable_values=variables, get_execution_result=True
|
369
367
|
)
|
370
368
|
except client_exceptions.ClientConnectorError as exception:
|
371
|
-
message = "
|
369
|
+
message = "[*] Failed to update hardware system info! "
|
372
370
|
logger.exception(message)
|
373
371
|
raise exception
|
374
372
|
|
375
|
-
message = "
|
373
|
+
message = "[*] Updated hardware system info successfully! "
|
376
374
|
logger.info(message)
|
377
375
|
|
378
376
|
return result
|
@@ -416,7 +414,6 @@ class Hardware(BaseAction):
|
|
416
414
|
checkin_success = result.data.get("checkIn").get("lastCheckIn")
|
417
415
|
if messages := result.data.get("checkIn").get("messages"):
|
418
416
|
for message in messages:
|
419
|
-
logger.enable("primitive")
|
420
417
|
if message.get("kind") == "ERROR":
|
421
418
|
logger.error(message.get("message"))
|
422
419
|
else:
|
@@ -435,7 +432,7 @@ class Hardware(BaseAction):
|
|
435
432
|
}
|
436
433
|
self.status_cache[fingerprint] = new_state.copy()
|
437
434
|
|
438
|
-
message = f"
|
435
|
+
message = f"[*] Checked in successfully for {fingerprint}: "
|
439
436
|
is_new_status = False
|
440
437
|
for key, value in new_state.items():
|
441
438
|
if value != previous_status.get(key, None):
|
@@ -463,7 +460,7 @@ class Hardware(BaseAction):
|
|
463
460
|
return result
|
464
461
|
except client_exceptions.ClientConnectorError as exception:
|
465
462
|
if not stopping_agent:
|
466
|
-
message = "
|
463
|
+
message = "[*] Failed to check in! "
|
467
464
|
logger.error(message)
|
468
465
|
raise exception
|
469
466
|
else:
|
@@ -578,7 +575,6 @@ class Hardware(BaseAction):
|
|
578
575
|
|
579
576
|
if messages := result.data.get("registerChildHardware").get("messages"):
|
580
577
|
for message in messages:
|
581
|
-
logger.enable("primitive")
|
582
578
|
if message.get("kind") == "ERROR":
|
583
579
|
logger.error(message.get("message"))
|
584
580
|
else:
|