primitive 0.2.25__py3-none-any.whl → 0.2.27__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 +5 -5
- primitive/db/sqlite.py +25 -2
- primitive/hardware/actions.py +4 -4
- primitive/monitor/actions.py +39 -18
- primitive/monitor/commands.py +6 -4
- {primitive-0.2.25.dist-info → primitive-0.2.27.dist-info}/METADATA +1 -1
- {primitive-0.2.25.dist-info → primitive-0.2.27.dist-info}/RECORD +11 -11
- {primitive-0.2.25.dist-info → primitive-0.2.27.dist-info}/WHEEL +0 -0
- {primitive-0.2.25.dist-info → primitive-0.2.27.dist-info}/entry_points.txt +0 -0
- {primitive-0.2.25.dist-info → primitive-0.2.27.dist-info}/licenses/LICENSE.txt +0 -0
primitive/__about__.py
CHANGED
primitive/agent/actions.py
CHANGED
@@ -24,11 +24,11 @@ class Agent(BaseAction):
|
|
24
24
|
diagnose=True,
|
25
25
|
level="DEBUG" if self.primitive.DEBUG else "INFO",
|
26
26
|
)
|
27
|
-
logger.info("
|
28
|
-
logger.info(f"
|
27
|
+
logger.info("primitive agent")
|
28
|
+
logger.info(f"Version: {__version__}")
|
29
29
|
|
30
|
-
#
|
31
|
-
sqlite.
|
30
|
+
# Wait for monitor to make database
|
31
|
+
sqlite.wait_for_db()
|
32
32
|
|
33
33
|
# Create uploader
|
34
34
|
uploader = Uploader(primitive=self.primitive)
|
@@ -107,4 +107,4 @@ class Agent(BaseAction):
|
|
107
107
|
|
108
108
|
sleep(5)
|
109
109
|
except KeyboardInterrupt:
|
110
|
-
logger.info("[
|
110
|
+
logger.info("[agent] Stopping primitive agent...")
|
primitive/db/sqlite.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from pathlib import Path
|
2
|
+
from time import sleep
|
2
3
|
|
3
4
|
from loguru import logger
|
4
5
|
from sqlalchemy import Engine, create_engine
|
@@ -13,12 +14,12 @@ def init() -> None:
|
|
13
14
|
|
14
15
|
# Drop DB existing database if it exists
|
15
16
|
# if db_path.exists():
|
16
|
-
# logger.warning(f"
|
17
|
+
# logger.warning(f"Deleting existing SQLite database at {db_path}")
|
17
18
|
# db_path.unlink()
|
18
19
|
if db_path.exists():
|
19
20
|
return
|
20
21
|
|
21
|
-
logger.info(f"
|
22
|
+
logger.info(f"Initializing SQLite database at {db_path}")
|
22
23
|
engine = create_engine(f"sqlite:///{db_path}", echo=False)
|
23
24
|
Base.metadata.create_all(engine)
|
24
25
|
|
@@ -28,6 +29,28 @@ def engine() -> Engine:
|
|
28
29
|
return create_engine(f"sqlite:///{db_path}", echo=False)
|
29
30
|
|
30
31
|
|
32
|
+
def wait_for_db() -> None:
|
33
|
+
# Wait for the database to be created
|
34
|
+
db_path: Path = get_cache_dir() / "primitive.sqlite3"
|
35
|
+
|
36
|
+
max_tries = 60
|
37
|
+
current_try = 1
|
38
|
+
while not db_path.exists() and current_try <= max_tries:
|
39
|
+
logger.debug(
|
40
|
+
f"Waiting for SQLite database to be created... [{current_try} / {max_tries}]"
|
41
|
+
)
|
42
|
+
db_path.touch()
|
43
|
+
sleep(1)
|
44
|
+
current_try += 1
|
45
|
+
continue
|
46
|
+
if current_try > max_tries:
|
47
|
+
logger.error(
|
48
|
+
f"SQLite database was not created after {max_tries} tries. Exiting..."
|
49
|
+
)
|
50
|
+
raise RuntimeError("SQLite database was not created.")
|
51
|
+
logger.debug("SQLite database is ready.")
|
52
|
+
|
53
|
+
|
31
54
|
def Session() -> SQLAlchemySession:
|
32
55
|
from sqlalchemy.orm import sessionmaker
|
33
56
|
|
primitive/hardware/actions.py
CHANGED
@@ -366,11 +366,11 @@ class Hardware(BaseAction):
|
|
366
366
|
mutation, variable_values=variables, get_execution_result=True
|
367
367
|
)
|
368
368
|
except client_exceptions.ClientConnectorError as exception:
|
369
|
-
message = "
|
369
|
+
message = "Failed to update hardware system info! "
|
370
370
|
logger.exception(message)
|
371
371
|
raise exception
|
372
372
|
|
373
|
-
message = "
|
373
|
+
message = "Updated hardware system info successfully! "
|
374
374
|
logger.info(message)
|
375
375
|
|
376
376
|
return result
|
@@ -432,7 +432,7 @@ class Hardware(BaseAction):
|
|
432
432
|
}
|
433
433
|
self.status_cache[fingerprint] = new_state.copy()
|
434
434
|
|
435
|
-
message = f"
|
435
|
+
message = f"Checked in successfully for {fingerprint}: "
|
436
436
|
is_new_status = False
|
437
437
|
for key, value in new_state.items():
|
438
438
|
if value != previous_status.get(key, None):
|
@@ -460,7 +460,7 @@ class Hardware(BaseAction):
|
|
460
460
|
return result
|
461
461
|
except client_exceptions.ClientConnectorError as exception:
|
462
462
|
if not stopping_agent:
|
463
|
-
message = "
|
463
|
+
message = "Failed to check in! "
|
464
464
|
logger.error(message)
|
465
465
|
raise exception
|
466
466
|
else:
|
primitive/monitor/actions.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import sys
|
2
2
|
from time import sleep
|
3
|
+
from typing import Optional
|
3
4
|
|
4
5
|
import psutil
|
5
6
|
from loguru import logger
|
@@ -12,7 +13,7 @@ from primitive.utils.exceptions import P_CLI_100
|
|
12
13
|
|
13
14
|
|
14
15
|
class Monitor(BaseAction):
|
15
|
-
def start(self):
|
16
|
+
def start(self, job_run_id: Optional[str] = None):
|
16
17
|
logger.remove()
|
17
18
|
logger.add(
|
18
19
|
sink=sys.stderr,
|
@@ -21,24 +22,36 @@ class Monitor(BaseAction):
|
|
21
22
|
diagnose=True,
|
22
23
|
level="DEBUG" if self.primitive.DEBUG else "INFO",
|
23
24
|
)
|
24
|
-
logger.info("
|
25
|
-
logger.info(f"
|
25
|
+
logger.info("primitive monitor")
|
26
|
+
logger.info(f"Version: {__version__}")
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
# TODO: tighten logic for determining if we're running in a container
|
29
|
+
RUNNING_IN_CONTAINER = False
|
30
|
+
if job_run_id is not None:
|
31
|
+
logger.info("Running in container...")
|
32
|
+
RUNNING_IN_CONTAINER = True
|
33
|
+
|
34
|
+
# can't check if if it is a container
|
35
|
+
if not RUNNING_IN_CONTAINER:
|
36
|
+
try:
|
37
|
+
# hey stupid:
|
38
|
+
# do not set is_available to True here, it will mess up the reservation logic
|
39
|
+
# only set is_available after we've checked that no active reservation is present
|
40
|
+
# setting is_available of the parent also effects the children,
|
41
|
+
# which may have active reservations as well
|
42
|
+
self.primitive.hardware.check_in_http(is_online=True)
|
43
|
+
except Exception as exception:
|
44
|
+
logger.exception(f"Error checking in hardware: {exception}")
|
45
|
+
sys.exit(1)
|
37
46
|
|
38
47
|
# Initialize the database
|
39
48
|
sqlite.init()
|
40
49
|
|
41
50
|
try:
|
51
|
+
if job_run_id is not None:
|
52
|
+
JobRun.objects.create(job_run_id=job_run_id, pid=None)
|
53
|
+
logger.debug(f"Creating job run in database: {job_run_id}")
|
54
|
+
|
42
55
|
active_reservation_id = None
|
43
56
|
active_reservation_pk = None
|
44
57
|
|
@@ -95,6 +108,13 @@ class Monitor(BaseAction):
|
|
95
108
|
sleep(1)
|
96
109
|
continue
|
97
110
|
|
111
|
+
if RUNNING_IN_CONTAINER:
|
112
|
+
# if we get here and we're running in a container,
|
113
|
+
# it means the job run is complete and there is nothing left in the database
|
114
|
+
# so we can exit
|
115
|
+
logger.debug("Running in container, initial job complete.")
|
116
|
+
sys.exit(0)
|
117
|
+
|
98
118
|
# Second, check for active reservations
|
99
119
|
hardware = self.primitive.hardware.get_own_hardware_details()
|
100
120
|
if hardware["activeReservation"]:
|
@@ -187,13 +207,14 @@ class Monitor(BaseAction):
|
|
187
207
|
logger.debug(f"Creating job run in database: {job_run['id']}")
|
188
208
|
|
189
209
|
except KeyboardInterrupt:
|
190
|
-
logger.info("
|
210
|
+
logger.info("Stopping primitive monitor...")
|
191
211
|
try:
|
192
|
-
|
193
|
-
|
194
|
-
|
212
|
+
if not RUNNING_IN_CONTAINER:
|
213
|
+
self.primitive.hardware.check_in_http(
|
214
|
+
is_available=False, is_online=False, stopping_agent=True
|
215
|
+
)
|
195
216
|
|
196
217
|
except P_CLI_100 as exception:
|
197
|
-
logger.error("
|
218
|
+
logger.error("Error stopping primitive monitor.")
|
198
219
|
logger.error(str(exception))
|
199
220
|
sys.exit()
|
primitive/monitor/commands.py
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
2
|
+
|
1
3
|
import click
|
2
|
-
import typing
|
3
4
|
|
4
|
-
if
|
5
|
+
if TYPE_CHECKING:
|
5
6
|
from ..client import Primitive
|
6
7
|
|
7
8
|
|
8
9
|
@click.command("monitor")
|
10
|
+
@click.option("--job-run-id", type=str, help="Explicit Job Run to pull")
|
9
11
|
@click.pass_context
|
10
|
-
def cli(context):
|
12
|
+
def cli(context, job_run_id: Optional[str] = None):
|
11
13
|
"""monitor"""
|
12
14
|
primitive: Primitive = context.obj.get("PRIMITIVE")
|
13
|
-
primitive.monitor.start()
|
15
|
+
primitive.monitor.start(job_run_id=job_run_id)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: primitive
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.27
|
4
4
|
Project-URL: Documentation, https://github.com//primitivecorp/primitive-cli#readme
|
5
5
|
Project-URL: Issues, https://github.com//primitivecorp/primitive-cli/issues
|
6
6
|
Project-URL: Source, https://github.com//primitivecorp/primitive-cli
|
@@ -1,9 +1,9 @@
|
|
1
|
-
primitive/__about__.py,sha256=
|
1
|
+
primitive/__about__.py,sha256=DiY29pKV2K5D1JKr9jAi4jEELMktClhq9SkZurDA7L0,130
|
2
2
|
primitive/__init__.py,sha256=bwKdgggKNVssJFVPfKSxqFMz4IxSr54WWbmiZqTMPNI,106
|
3
3
|
primitive/cli.py,sha256=g7EtHI9MATAB0qQu5w-WzbXtxz_8zu8z5E7sETmMkKU,2509
|
4
4
|
primitive/client.py,sha256=h8WZVnQylVe0vbpuyC8YZHl2JyITSPC-1HbUcmrE5pc,3623
|
5
5
|
primitive/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
primitive/agent/actions.py,sha256=
|
6
|
+
primitive/agent/actions.py,sha256=bTzEaMOs5kK8cnJw6VvrGeJNrXmu8rr_-2-87k8uNkg,3786
|
7
7
|
primitive/agent/commands.py,sha256=cK7d3OcN5Z65gQWVZFQ-Y9ddw9Pes4f9OVBpeMsj5sE,255
|
8
8
|
primitive/agent/runner.py,sha256=CoRyReO3jPV8B7vILVWdszFD4GVop7HsVEUo1hoRXjo,14556
|
9
9
|
primitive/agent/uploader.py,sha256=ZzrzsajNBogwEC7mT6Ejy0h2Jd9axMYGzt9pbCvVMlk,3171
|
@@ -20,7 +20,7 @@ primitive/daemons/launch_service.py,sha256=iuklHeuEqadlf8U1n9xFg4ZG1EKdK2jyaPI-V
|
|
20
20
|
primitive/daemons/ui.py,sha256=Af3OJWJ0jdGlb1nfA5yaGYdhBEqqpM8zP2U2vUQdCbw,1236
|
21
21
|
primitive/db/base.py,sha256=mH7f2d_jiyxJSSx9Gk53QBXRa3LiKBsBjkFgvmtH1WA,83
|
22
22
|
primitive/db/models.py,sha256=GfnJdAq4Tb68CI4BKAuJDZVqioGavveaAHbCPeLNngw,2840
|
23
|
-
primitive/db/sqlite.py,sha256=
|
23
|
+
primitive/db/sqlite.py,sha256=chX4ih_TCn1Y-jJn8WGOC2prqBUIpRUJrUwQ2KaYsko,1659
|
24
24
|
primitive/exec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
25
|
primitive/exec/actions.py,sha256=4d_TCjNDcVFoZ9Zw7ZuBa6hKMv2Xzm7_UX_8wcX1aSk,4124
|
26
26
|
primitive/exec/commands.py,sha256=66LO2kkJC-ynNZQpUCXv4Ol15QoacdSZAHblePDcmLo,510
|
@@ -42,7 +42,7 @@ primitive/graphql/relay.py,sha256=bmij2AjdpURQ6GGVCxwWhauF-r_SxuAU2oJ4sDbLxpI,72
|
|
42
42
|
primitive/graphql/sdk.py,sha256=KhVWDZms_eMBgt6ftSJitRALguagy-nmrj4IC2taeXY,1535
|
43
43
|
primitive/graphql/utility_fragments.py,sha256=uIjwILC4QtWNyO5vu77VjQf_p0jvP3A9q_6zRq91zqs,303
|
44
44
|
primitive/hardware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
-
primitive/hardware/actions.py,sha256=
|
45
|
+
primitive/hardware/actions.py,sha256=qBMcCcgSf3XRe-ua1unf5M64J-Y8EelUQKysa8vje0s,26060
|
46
46
|
primitive/hardware/android.py,sha256=tu7pBPxWFrIwb_mm5CEdFFf1_veNDOKjOCQg13i_Lh4,2758
|
47
47
|
primitive/hardware/commands.py,sha256=NMliVHBZDl4UAvhmNEjrvN9KWPuqn87-d7eVb0ZqEYA,3752
|
48
48
|
primitive/hardware/ui.py,sha256=12rucuZ2s-w5R4bKyxON5dEbrdDnVf5sbj3K_nbdo44,2473
|
@@ -57,8 +57,8 @@ primitive/jobs/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
57
57
|
primitive/jobs/graphql/fragments.py,sha256=1_ZttT7dx36KDC3DClJz9M8LMpsPwXySBygHSiUEcGg,619
|
58
58
|
primitive/jobs/graphql/mutations.py,sha256=8ASvCmwQh7cMeeiykOdYaYVryG8FRIuVF6v_J8JJZuw,219
|
59
59
|
primitive/jobs/graphql/queries.py,sha256=BrU_GnLjK0bTAmWsLSmGEUea7EM8MqTKxN1Qp6sSjwc,1597
|
60
|
-
primitive/monitor/actions.py,sha256=
|
61
|
-
primitive/monitor/commands.py,sha256=
|
60
|
+
primitive/monitor/actions.py,sha256=kgXzj45B-mFZke06pOHdKJ4RTDo32_YRV5hMpS65Pjk,9706
|
61
|
+
primitive/monitor/commands.py,sha256=VDlEL_Qpm_ysHxug7VpI0cVAZ0ny6AS91Y58D7F1zkU,409
|
62
62
|
primitive/organizations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
63
|
primitive/organizations/actions.py,sha256=kVHOhG1oS2sI5p8uldSo5L-RUZsnG36eaulVuKLyZ-M,1863
|
64
64
|
primitive/organizations/commands.py,sha256=_dwgVEJCqMa5VgB_7P1wLPFc0AuT1p9dtyR9JRr4kpw,487
|
@@ -96,8 +96,8 @@ primitive/utils/memory_size.py,sha256=4xfha21kW82nFvOTtDFx9Jk2ZQoEhkfXii-PGNTpIU
|
|
96
96
|
primitive/utils/printer.py,sha256=f1XUpqi5dkTL3GWvYRUGlSwtj2IxU1q745T4Fxo7Tn4,370
|
97
97
|
primitive/utils/shell.py,sha256=jWzb7ky7p987dJas6ZvarK3IJNZ5cwBXcryRWb9Uh6U,2072
|
98
98
|
primitive/utils/text.py,sha256=XiESMnlhjQ534xE2hMNf08WehE1SKaYFRNih0MmnK0k,829
|
99
|
-
primitive-0.2.
|
100
|
-
primitive-0.2.
|
101
|
-
primitive-0.2.
|
102
|
-
primitive-0.2.
|
103
|
-
primitive-0.2.
|
99
|
+
primitive-0.2.27.dist-info/METADATA,sha256=CaxlEEfLCa1XxJ6ydce8TLWbPShjNVzfrJgUxHn6PXo,3569
|
100
|
+
primitive-0.2.27.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
101
|
+
primitive-0.2.27.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
|
102
|
+
primitive-0.2.27.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
|
103
|
+
primitive-0.2.27.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|