primitive 0.2.26__py3-none-any.whl → 0.2.28__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2024-present Dylan Stein <dylan@primitive.tech>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.2.26"
4
+ __version__ = "0.2.28"
@@ -4,13 +4,12 @@ from time import sleep
4
4
  from loguru import logger
5
5
 
6
6
  from primitive.__about__ import __version__
7
+ from primitive.agent.runner import Runner
8
+ from primitive.agent.uploader import Uploader
9
+ from primitive.db import sqlite
10
+ from primitive.db.models import JobRun
7
11
  from primitive.utils.actions import BaseAction
8
12
 
9
- from ..db import sqlite
10
- from ..db.models import JobRun
11
- from .runner import Runner
12
- from .uploader import Uploader
13
-
14
13
 
15
14
  class Agent(BaseAction):
16
15
  def execute(
@@ -24,11 +23,11 @@ class Agent(BaseAction):
24
23
  diagnose=True,
25
24
  level="DEBUG" if self.primitive.DEBUG else "INFO",
26
25
  )
27
- logger.info("[*] primitive agent")
28
- logger.info(f"[*] Version: {__version__}")
26
+ logger.info("primitive agent")
27
+ logger.info(f"Version: {__version__}")
29
28
 
30
- # Initialize the database
31
- sqlite.init()
29
+ # Wait for monitor to make database
30
+ sqlite.wait_for_db()
32
31
 
33
32
  # Create uploader
34
33
  uploader = Uploader(primitive=self.primitive)
@@ -107,4 +106,4 @@ class Agent(BaseAction):
107
106
 
108
107
  sleep(5)
109
108
  except KeyboardInterrupt:
110
- logger.info("[*] Stopping primitive agent...")
109
+ logger.info("[agent] Stopping primitive agent...")
primitive/db/sqlite.py CHANGED
@@ -1,11 +1,12 @@
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
5
6
  from sqlalchemy.orm import Session as SQLAlchemySession
6
7
 
7
- from ..utils.cache import get_cache_dir
8
- from .base import Base
8
+ from primitive.db.base import Base
9
+ from primitive.utils.cache import get_cache_dir
9
10
 
10
11
 
11
12
  def init() -> None:
@@ -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"[*] Deleting existing SQLite database at {db_path}")
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"[*] Initializing SQLite database at {db_path}")
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
 
@@ -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 = "[*] Failed to update hardware system info! "
369
+ message = "Failed to update hardware system info! "
370
370
  logger.exception(message)
371
371
  raise exception
372
372
 
373
- message = "[*] Updated hardware system info successfully! "
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"[*] Checked in successfully for {fingerprint}: "
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 = "[*] Failed to check in! "
463
+ message = "Failed to check in! "
464
464
  logger.error(message)
465
465
  raise exception
466
466
  else:
@@ -22,13 +22,13 @@ class Monitor(BaseAction):
22
22
  diagnose=True,
23
23
  level="DEBUG" if self.primitive.DEBUG else "INFO",
24
24
  )
25
- logger.info("[*] primitive monitor")
26
- logger.info(f"[*] Version: {__version__}")
25
+ logger.info("primitive monitor")
26
+ logger.info(f"Version: {__version__}")
27
27
 
28
28
  # TODO: tighten logic for determining if we're running in a container
29
29
  RUNNING_IN_CONTAINER = False
30
30
  if job_run_id is not None:
31
- logger.info("[*] Running in container...")
31
+ logger.info("Running in container...")
32
32
  RUNNING_IN_CONTAINER = True
33
33
 
34
34
  # can't check if if it is a container
@@ -49,8 +49,10 @@ class Monitor(BaseAction):
49
49
 
50
50
  try:
51
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}")
52
+ if not JobRun.objects.filter_by(job_run_id=job_run_id).exists():
53
+ logger.debug(f"Job run {job_run_id} does not exist in database.")
54
+ logger.debug(f"Creating job run in database: {job_run_id}")
55
+ JobRun.objects.create(job_run_id=job_run_id, pid=None)
54
56
 
55
57
  active_reservation_id = None
56
58
  active_reservation_pk = None
@@ -68,6 +70,7 @@ class Monitor(BaseAction):
68
70
  f"Sleeping {pid_sleep_amount} seconds before checking again..."
69
71
  )
70
72
  sleep(pid_sleep_amount)
73
+ pid_sleep_amount += 0.1
71
74
  continue
72
75
 
73
76
  logger.debug(
@@ -109,11 +112,14 @@ class Monitor(BaseAction):
109
112
  continue
110
113
 
111
114
  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)
115
+ if len(db_job_runs) == 0:
116
+ # if we get here and we're running in a container,
117
+ # it means the job run is complete and there is nothing left in the database
118
+ # so we can exit
119
+ logger.debug("Running in container, initial job complete.")
120
+ sys.exit(0)
121
+ else:
122
+ continue
117
123
 
118
124
  # Second, check for active reservations
119
125
  hardware = self.primitive.hardware.get_own_hardware_details()
@@ -207,7 +213,7 @@ class Monitor(BaseAction):
207
213
  logger.debug(f"Creating job run in database: {job_run['id']}")
208
214
 
209
215
  except KeyboardInterrupt:
210
- logger.info("[*] Stopping primitive monitor...")
216
+ logger.info("Stopping primitive monitor...")
211
217
  try:
212
218
  if not RUNNING_IN_CONTAINER:
213
219
  self.primitive.hardware.check_in_http(
@@ -215,6 +221,6 @@ class Monitor(BaseAction):
215
221
  )
216
222
 
217
223
  except P_CLI_100 as exception:
218
- logger.error("[*] Error stopping primitive monitor.")
224
+ logger.error("Error stopping primitive monitor.")
219
225
  logger.error(str(exception))
220
226
  sys.exit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: primitive
3
- Version: 0.2.26
3
+ Version: 0.2.28
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=oMpyVg2UpvXjSCtuQGv9QEUGqwIl1DtBLRAtQa5pBhE,130
1
+ primitive/__about__.py,sha256=TN5q_6fZsIHlzQAAdwHQoUozl_mXtvh_nCPeIoE5zEQ,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=PzFOgxuRrhbUGpUygnTZVru58Fv87GI8tgJYkZB1LjI,3773
6
+ primitive/agent/actions.py,sha256=5etkxo1ylmNlgFY3AELnVoTEZamhN-wCb8pdskA2mWM,3831
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=3V9ZxbgME1ThfJp90MPLUxU8b9imgNZM5CHOnA-WkaQ,953
23
+ primitive/db/sqlite.py,sha256=EJx80xPJ4PP2bso6qPaKys1-jfRTmYi_qYxPaFWM4iI,1679
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=d5KwuSsceOhDH9rgOL7YTCpQPhqT2inRTiZnROtiDic,26076
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,7 +57,7 @@ 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=Fem8i-I1CZnLGNCHq8gKqURTHUtfmYEJ9h5zAv1wD18,9726
60
+ primitive/monitor/actions.py,sha256=cFCsQZvTwkmcWGPwNgop4fKQX4VWLRKJz_2c7_s9bII,10054
61
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
@@ -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.26.dist-info/METADATA,sha256=IJmRQR_Wu5dMULSvjr_n0Pp5CIFDMGlrixZAuxtVUJ0,3569
100
- primitive-0.2.26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
101
- primitive-0.2.26.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
102
- primitive-0.2.26.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
103
- primitive-0.2.26.dist-info/RECORD,,
99
+ primitive-0.2.28.dist-info/METADATA,sha256=SWVPvj72QFr4vA9JmhfeCRP593o1L1t_I8RxwPsqXhw,3569
100
+ primitive-0.2.28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
101
+ primitive-0.2.28.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
102
+ primitive-0.2.28.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
103
+ primitive-0.2.28.dist-info/RECORD,,