primitive 0.2.70__tar.gz → 0.2.72__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.
Potentially problematic release.
This version of primitive might be problematic. Click here for more details.
- {primitive-0.2.70 → primitive-0.2.72}/.vscode/settings.json +1 -0
- {primitive-0.2.70 → primitive-0.2.72}/PKG-INFO +1 -1
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/__about__.py +1 -1
- primitive-0.2.72/src/primitive/agent/pxe.py +71 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/agent/runner.py +2 -25
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/actions.py +13 -2
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/messaging/provider.py +1 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/monitor/actions.py +1 -1
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/actions.py +6 -10
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/ssh.py +16 -7
- primitive-0.2.72/src/primitive/operating_systems/actions.py +473 -0
- primitive-0.2.72/src/primitive/operating_systems/commands.py +246 -0
- primitive-0.2.72/testing_containers/README.md +21 -0
- {primitive-0.2.70 → primitive-0.2.72}/testing_containers/fedora.Containerfile +4 -3
- {primitive-0.2.70 → primitive-0.2.72}/testing_containers/ubuntu.Containerfile +4 -3
- primitive-0.2.70/src/primitive/operating_systems/actions.py +0 -260
- primitive-0.2.70/src/primitive/operating_systems/commands.py +0 -268
- primitive-0.2.70/testing_containers/README.md +0 -13
- {primitive-0.2.70 → primitive-0.2.72}/.git-hooks/pre-commit +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.gitattributes +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.github/workflows/lint.yml +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.github/workflows/publish.yml +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.github/workflows/pyright.yml +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.gitignore +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/.vscode/extensions.json +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/LICENSE.txt +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/Makefile +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/README.md +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/linux setup.md +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/pyproject.toml +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/agent/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/agent/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/agent/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/agent/uploader.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/auth/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/auth/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/auth/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/auth/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/auth/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/cli.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/client.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/launch_agents.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/launch_service.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/daemons/ui.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/exec/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/exec/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/exec/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/exec/interactive.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/files/ui.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/git/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/git/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/git/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/git/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/git/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/graphql/relay.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/graphql/sdk.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/graphql/utility_fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/android.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/hardware/ui.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/jobs/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/messaging/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/monitor/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/redfish.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/network/ui.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/operating_systems/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/operating_systems/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/operating_systems/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/operating_systems/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/organizations/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/projects/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/provisioning/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/provisioning/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/provisioning/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/provisioning/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/commands.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/graphql/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/graphql/fragments.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/graphql/mutations.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/reservations/graphql/queries.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/actions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/auth.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/cache.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/checksums.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/chunk_size.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/config.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/daemons.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/exceptions.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/logging.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/memory_size.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/printer.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/psutil.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/shell.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/text.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/src/primitive/utils/x509.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/tests/__init__.py +0 -0
- {primitive-0.2.70 → primitive-0.2.72}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: primitive
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.72
|
|
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
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from loguru import logger
|
|
2
|
+
|
|
3
|
+
from primitive.network.redfish import RedfishClient
|
|
4
|
+
from primitive.network.ssh import test_ssh_connection, run_command
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def pxe_boot_via_redfish(target_hardware_secret: dict):
|
|
8
|
+
bmc_host = target_hardware_secret.get("bmcHostname", None)
|
|
9
|
+
bmc_username = target_hardware_secret.get("bmcUsername", None)
|
|
10
|
+
bmc_password = target_hardware_secret.get("bmcPassword", "")
|
|
11
|
+
|
|
12
|
+
if bmc_host is None:
|
|
13
|
+
logger.error(
|
|
14
|
+
"No BMC host found in target hardware secret for out-of-band power cycle"
|
|
15
|
+
)
|
|
16
|
+
return True
|
|
17
|
+
if bmc_username is None:
|
|
18
|
+
logger.error(
|
|
19
|
+
"No BMC username found in target hardware secret for out-of-band power cycle"
|
|
20
|
+
)
|
|
21
|
+
return True
|
|
22
|
+
|
|
23
|
+
redfish = RedfishClient(host=bmc_host, username=bmc_username, password=bmc_password)
|
|
24
|
+
redfish.update_boot_options(
|
|
25
|
+
system_id="1",
|
|
26
|
+
boot_source_override_target="Pxe",
|
|
27
|
+
boot_source_override_enabled="Once",
|
|
28
|
+
boot_source_override_mode="UEFI",
|
|
29
|
+
)
|
|
30
|
+
redfish.compute_system_reset(system_id="1", reset_type="ForceRestart")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def pxe_boot_via_efibootmgr(target_hardware_secret: dict):
|
|
34
|
+
run_command(
|
|
35
|
+
hostname=target_hardware_secret.get("hostname"),
|
|
36
|
+
username=target_hardware_secret.get("username"),
|
|
37
|
+
password=target_hardware_secret.get("password"),
|
|
38
|
+
command="sudo efibootmgr -n $(efibootmgr | awk '/PXE IPV4/ {print substr($1,5,4)}' | head -n1 || efibootmgr | awk '/ubuntu/ {print substr($1,5,4)}' | head -n1) && sudo reboot",
|
|
39
|
+
port=22,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def pxe_boot(target_hardware_secret: dict) -> bool:
|
|
44
|
+
redfish_available = False
|
|
45
|
+
ssh_available = False
|
|
46
|
+
|
|
47
|
+
if target_hardware_secret.get("bmcHostname", None):
|
|
48
|
+
redfish_available = True
|
|
49
|
+
else:
|
|
50
|
+
logger.info(
|
|
51
|
+
"No BMC credentials found, skipping Redfish PXE boot method. Checking efiboot method."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
ssh_available = test_ssh_connection(
|
|
55
|
+
hostname=target_hardware_secret.get("hostname"),
|
|
56
|
+
username=target_hardware_secret.get("username"),
|
|
57
|
+
password=target_hardware_secret.get("password"),
|
|
58
|
+
port=22,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if redfish_available:
|
|
62
|
+
pxe_boot_via_redfish(target_hardware_secret=target_hardware_secret)
|
|
63
|
+
return True
|
|
64
|
+
elif ssh_available:
|
|
65
|
+
pxe_boot_via_efibootmgr(target_hardware_secret=target_hardware_secret)
|
|
66
|
+
return True
|
|
67
|
+
else:
|
|
68
|
+
logger.error(
|
|
69
|
+
"No available method to PXE boot target hardware. Missing BMC credentials and SSH is not available."
|
|
70
|
+
)
|
|
71
|
+
return False
|
|
@@ -10,6 +10,7 @@ from datetime import datetime, timezone
|
|
|
10
10
|
|
|
11
11
|
from loguru import logger
|
|
12
12
|
|
|
13
|
+
from primitive.agent.pxe import pxe_boot
|
|
13
14
|
from primitive.network.ssh import wait_for_ssh
|
|
14
15
|
from primitive.utils.cache import get_artifacts_cache, get_logs_cache, get_sources_cache
|
|
15
16
|
from primitive.utils.logging import fmt, log_context
|
|
@@ -287,33 +288,9 @@ class Runner:
|
|
|
287
288
|
|
|
288
289
|
if cmd == "pxeboot":
|
|
289
290
|
logger.info("Setting next boot to PXE and rebooting")
|
|
290
|
-
from primitive.network.redfish import RedfishClient
|
|
291
|
-
|
|
292
|
-
bmc_host = self.target_hardware_secret.get("bmcHostname", None)
|
|
293
|
-
bmc_username = self.target_hardware_secret.get("bmcUsername", None)
|
|
294
|
-
bmc_password = self.target_hardware_secret.get("bmcPassword", "")
|
|
295
291
|
|
|
296
|
-
|
|
297
|
-
logger.error(
|
|
298
|
-
"No BMC host found in target hardware secret for out-of-band power cycle"
|
|
299
|
-
)
|
|
300
|
-
return True
|
|
301
|
-
if bmc_username is None:
|
|
302
|
-
logger.error(
|
|
303
|
-
"No BMC username found in target hardware secret for out-of-band power cycle"
|
|
304
|
-
)
|
|
305
|
-
return True
|
|
292
|
+
pxe_boot(target_hardware_secret=self.target_hardware_secret)
|
|
306
293
|
|
|
307
|
-
redfish = RedfishClient(
|
|
308
|
-
host=bmc_host, username=bmc_username, password=bmc_password
|
|
309
|
-
)
|
|
310
|
-
redfish.update_boot_options(
|
|
311
|
-
system_id="1",
|
|
312
|
-
boot_source_override_target="Pxe",
|
|
313
|
-
boot_source_override_enabled="Once",
|
|
314
|
-
boot_source_override_mode="UEFI",
|
|
315
|
-
)
|
|
316
|
-
redfish.compute_system_reset(system_id="1", reset_type="ForceRestart")
|
|
317
294
|
if self.target_hardware_id:
|
|
318
295
|
await self.primitive.hardware.aupdate_hardware(
|
|
319
296
|
hardware_id=self.target_hardware_id,
|
|
@@ -421,7 +421,10 @@ class Hardware(BaseAction):
|
|
|
421
421
|
def _get_ubuntu_installed_packages(self):
|
|
422
422
|
try:
|
|
423
423
|
lines = (
|
|
424
|
-
subprocess.check_output(
|
|
424
|
+
subprocess.check_output(
|
|
425
|
+
["apt", "list", "--installed"],
|
|
426
|
+
stderr=subprocess.DEVNULL,
|
|
427
|
+
)
|
|
425
428
|
.decode("utf-8")
|
|
426
429
|
.strip()
|
|
427
430
|
.split("\n")
|
|
@@ -793,7 +796,7 @@ class Hardware(BaseAction):
|
|
|
793
796
|
if slug is not None:
|
|
794
797
|
filters["slug"] = {"exact": slug}
|
|
795
798
|
if id is not None:
|
|
796
|
-
filters["id"] =
|
|
799
|
+
filters["id"] = id
|
|
797
800
|
# if nested_children is True:
|
|
798
801
|
# filters["hasParent"] = {"exact": False}
|
|
799
802
|
|
|
@@ -1206,3 +1209,11 @@ class Hardware(BaseAction):
|
|
|
1206
1209
|
logger.info(message)
|
|
1207
1210
|
|
|
1208
1211
|
return result
|
|
1212
|
+
|
|
1213
|
+
def push_own_system_info(self):
|
|
1214
|
+
if self.primitive.messaging.ready:
|
|
1215
|
+
message = {"system_info": self.primitive.hardware.get_system_info()}
|
|
1216
|
+
self.primitive.messaging.send_message(
|
|
1217
|
+
message_type=MESSAGE_TYPES.SYSTEM_INFO,
|
|
1218
|
+
message=message,
|
|
1219
|
+
)
|
|
@@ -27,6 +27,7 @@ CELERY_TASK_NAME = "hardware.tasks.task_receive_hardware_message"
|
|
|
27
27
|
|
|
28
28
|
class MESSAGE_TYPES(enum.Enum):
|
|
29
29
|
CHECK_IN = "CHECK_IN"
|
|
30
|
+
SYSTEM_INFO = "SYSTEM_INFO"
|
|
30
31
|
METRICS = "METRICS"
|
|
31
32
|
SWITCH_AND_INTERFACES_INFO = "SWITCH_AND_INTERFACES_INFO"
|
|
32
33
|
OWN_NETWORK_INTERFACES = "OWN_NETWORK_INTERFACES"
|
|
@@ -94,7 +94,7 @@ class Monitor(BaseAction):
|
|
|
94
94
|
if hardware.get("isController", False):
|
|
95
95
|
self.primitive.hardware.get_and_set_switch_info()
|
|
96
96
|
self.primitive.network.push_switch_and_interfaces_info()
|
|
97
|
-
self.primitive.
|
|
97
|
+
self.primitive.hardware.push_own_system_info()
|
|
98
98
|
self.primitive.hardware._sync_children(hardware=hardware)
|
|
99
99
|
|
|
100
100
|
sleep_amount = 5
|
|
@@ -8,6 +8,7 @@ from paramiko import SSHClient
|
|
|
8
8
|
from typing import TypedDict
|
|
9
9
|
import re
|
|
10
10
|
|
|
11
|
+
from primitive.hardware.actions import does_executable_exist
|
|
11
12
|
from primitive.messaging.provider import MESSAGE_TYPES
|
|
12
13
|
from primitive.utils.actions import BaseAction
|
|
13
14
|
|
|
@@ -372,6 +373,9 @@ class Network(BaseAction):
|
|
|
372
373
|
return ip_to_mac_address_info
|
|
373
374
|
|
|
374
375
|
def get_ip_arp_table_via_ip_command(self):
|
|
376
|
+
if does_executable_exist("ip") is False:
|
|
377
|
+
return []
|
|
378
|
+
|
|
375
379
|
command = "ip --json neigh show"
|
|
376
380
|
ip_result = None
|
|
377
381
|
with Popen(command.split(" "), stdout=PIPE) as process:
|
|
@@ -458,6 +462,7 @@ class Network(BaseAction):
|
|
|
458
462
|
return False
|
|
459
463
|
|
|
460
464
|
def push_switch_and_interfaces_info(self, interfaces_info: dict | None = None):
|
|
465
|
+
logger.debug("Pushing switch and interfaces info")
|
|
461
466
|
if self.primitive.messaging.ready and self.switch_connection_info is not None:
|
|
462
467
|
switch_info = self.get_switch_info()
|
|
463
468
|
interfaces_info = interfaces_info or self.get_interfaces_info()
|
|
@@ -473,13 +478,4 @@ class Network(BaseAction):
|
|
|
473
478
|
message_type=MESSAGE_TYPES.SWITCH_AND_INTERFACES_INFO,
|
|
474
479
|
message=message,
|
|
475
480
|
)
|
|
476
|
-
|
|
477
|
-
def push_own_network_interfaces(self):
|
|
478
|
-
if self.primitive.messaging.ready:
|
|
479
|
-
message = {
|
|
480
|
-
"network_interfaces": self.primitive.hardware._get_network_interfaces()
|
|
481
|
-
}
|
|
482
|
-
self.primitive.messaging.send_message(
|
|
483
|
-
message_type=MESSAGE_TYPES.OWN_NETWORK_INTERFACES,
|
|
484
|
-
message=message,
|
|
485
|
-
)
|
|
481
|
+
logger.debug("Switch and interfaces info pushed")
|
|
@@ -27,7 +27,13 @@ def test_ssh_connection(hostname, username, password=None, key_filename=None, po
|
|
|
27
27
|
try:
|
|
28
28
|
if password:
|
|
29
29
|
ssh_client.connect(
|
|
30
|
-
hostname=hostname,
|
|
30
|
+
hostname=hostname,
|
|
31
|
+
port=port,
|
|
32
|
+
username=username,
|
|
33
|
+
password=password,
|
|
34
|
+
banner_timeout=60,
|
|
35
|
+
timeout=60,
|
|
36
|
+
auth_timeout=60,
|
|
31
37
|
)
|
|
32
38
|
elif key_filename:
|
|
33
39
|
ssh_client.connect(
|
|
@@ -35,26 +41,29 @@ def test_ssh_connection(hostname, username, password=None, key_filename=None, po
|
|
|
35
41
|
port=port,
|
|
36
42
|
username=username,
|
|
37
43
|
key_filename=key_filename,
|
|
44
|
+
banner_timeout=60,
|
|
45
|
+
timeout=60,
|
|
46
|
+
auth_timeout=60,
|
|
38
47
|
)
|
|
39
48
|
else:
|
|
40
|
-
|
|
49
|
+
logger.error(
|
|
41
50
|
"Error: Either password or key_filename must be provided for authentication."
|
|
42
51
|
)
|
|
43
52
|
return False
|
|
44
53
|
|
|
45
|
-
|
|
54
|
+
logger.info(f"Successfully connected to {hostname} as {username}")
|
|
46
55
|
return True
|
|
47
56
|
except paramiko.AuthenticationException:
|
|
48
|
-
|
|
57
|
+
logger.debug(f"Authentication failed for {username} on {hostname}")
|
|
49
58
|
return False
|
|
50
59
|
except paramiko.SSHException as exception:
|
|
51
|
-
|
|
60
|
+
logger.debug(f"SSH error connecting to {hostname}: {exception}")
|
|
52
61
|
return False
|
|
53
62
|
except socket.error as exception:
|
|
54
|
-
|
|
63
|
+
logger.debug(f"Socket error connecting to {hostname}: {exception}")
|
|
55
64
|
return False
|
|
56
65
|
except Exception as exception:
|
|
57
|
-
|
|
66
|
+
logger.debug(f"An unexpected error occurred: {exception}")
|
|
58
67
|
return False
|
|
59
68
|
finally:
|
|
60
69
|
ssh_client.close()
|