primitive 0.2.63__py3-none-any.whl → 0.2.66__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.
Potentially problematic release.
This version of primitive might be problematic. Click here for more details.
- primitive/__about__.py +1 -1
- primitive/agent/actions.py +33 -3
- primitive/agent/runner.py +99 -3
- primitive/cli.py +2 -0
- primitive/client.py +2 -0
- primitive/hardware/actions.py +232 -15
- primitive/hardware/commands.py +8 -2
- primitive/hardware/graphql/fragments.py +10 -0
- primitive/hardware/graphql/mutations.py +16 -1
- primitive/hardware/graphql/queries.py +48 -0
- primitive/jobs/graphql/fragments.py +4 -0
- primitive/messaging/provider.py +9 -4
- primitive/monitor/actions.py +28 -6
- primitive/network/__init__.py +0 -0
- primitive/network/actions.py +436 -0
- primitive/network/commands.py +40 -0
- primitive/network/redfish.py +121 -0
- primitive/network/ui.py +19 -0
- {primitive-0.2.63.dist-info → primitive-0.2.66.dist-info}/METADATA +2 -1
- {primitive-0.2.63.dist-info → primitive-0.2.66.dist-info}/RECORD +23 -18
- {primitive-0.2.63.dist-info → primitive-0.2.66.dist-info}/WHEEL +0 -0
- {primitive-0.2.63.dist-info → primitive-0.2.66.dist-info}/entry_points.txt +0 -0
- {primitive-0.2.63.dist-info → primitive-0.2.66.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RedfishClient:
|
|
6
|
+
def __init__(self, host: str, username: str, password: str):
|
|
7
|
+
self.host = host
|
|
8
|
+
self.username = username
|
|
9
|
+
self.password = password
|
|
10
|
+
|
|
11
|
+
def create_session_token(self):
|
|
12
|
+
response = requests.post(
|
|
13
|
+
f"https://{self.host}/redfish/v1/SessionService/Sessions",
|
|
14
|
+
json={"UserName": self.username, "Password": self.password},
|
|
15
|
+
verify=False,
|
|
16
|
+
)
|
|
17
|
+
response.raise_for_status()
|
|
18
|
+
return response.headers["X-Auth-Token"]
|
|
19
|
+
|
|
20
|
+
def get_systems(self):
|
|
21
|
+
token = self.create_session_token()
|
|
22
|
+
headers = {"X-Auth-Token": token}
|
|
23
|
+
response = requests.get(
|
|
24
|
+
f"https://{self.host}/redfish/v1/Systems",
|
|
25
|
+
headers=headers,
|
|
26
|
+
verify=False,
|
|
27
|
+
)
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
return response.json()
|
|
30
|
+
|
|
31
|
+
def get_system(self, system_id: str):
|
|
32
|
+
token = self.create_session_token()
|
|
33
|
+
headers = {"X-Auth-Token": token}
|
|
34
|
+
response = requests.get(
|
|
35
|
+
f"https://{self.host}/redfish/v1/Systems/{system_id}",
|
|
36
|
+
headers=headers,
|
|
37
|
+
verify=False,
|
|
38
|
+
)
|
|
39
|
+
response.raise_for_status()
|
|
40
|
+
return response.json()
|
|
41
|
+
|
|
42
|
+
def update_boot_options(
|
|
43
|
+
self,
|
|
44
|
+
system_id: str,
|
|
45
|
+
boot_source_override_enabled: Literal["Once", "Continuous", "Disabled"],
|
|
46
|
+
boot_source_override_target: Literal[
|
|
47
|
+
"None", "Pxe", "Cd", "Usb", "Hdd", "BiosSetup", "Diags", "UefiTarget"
|
|
48
|
+
],
|
|
49
|
+
boot_source_override_mode: Literal["UEFI", "Legacy"] = "UEFI",
|
|
50
|
+
):
|
|
51
|
+
token = self.create_session_token()
|
|
52
|
+
headers = {"X-Auth-Token": token}
|
|
53
|
+
body = {
|
|
54
|
+
"Boot": {
|
|
55
|
+
"BootSourceOverrideTarget": boot_source_override_target,
|
|
56
|
+
"BootSourceOverrideEnabled": boot_source_override_enabled,
|
|
57
|
+
"BootSourceOverrideMode": boot_source_override_mode,
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
response = requests.patch(
|
|
61
|
+
f"https://{self.host}/redfish/v1/Systems/{system_id}",
|
|
62
|
+
headers=headers,
|
|
63
|
+
verify=False,
|
|
64
|
+
json=body,
|
|
65
|
+
)
|
|
66
|
+
response.raise_for_status()
|
|
67
|
+
return response.json()
|
|
68
|
+
|
|
69
|
+
def get_boot_options(self, system_id: str):
|
|
70
|
+
token = self.create_session_token()
|
|
71
|
+
headers = {"X-Auth-Token": token}
|
|
72
|
+
response = requests.get(
|
|
73
|
+
f"https://{self.host}/redfish/v1/Systems/{system_id}/BootOptions",
|
|
74
|
+
headers=headers,
|
|
75
|
+
verify=False,
|
|
76
|
+
)
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
return response.json()
|
|
79
|
+
|
|
80
|
+
def get_boot_option(self, system_id: str, option_id: str):
|
|
81
|
+
# option_id typically looks like Boot000X
|
|
82
|
+
token = self.create_session_token()
|
|
83
|
+
headers = {"X-Auth-Token": token}
|
|
84
|
+
response = requests.get(
|
|
85
|
+
f"https://{self.host}/redfish/v1/Systems/{system_id}/BootOptions/{option_id}",
|
|
86
|
+
headers=headers,
|
|
87
|
+
verify=False,
|
|
88
|
+
)
|
|
89
|
+
response.raise_for_status()
|
|
90
|
+
return response.json()
|
|
91
|
+
|
|
92
|
+
def get_pxe_boot_option(self, system_id: str):
|
|
93
|
+
boot_options = self.get_boot_options(system_id)
|
|
94
|
+
for option in boot_options.get("Members", []):
|
|
95
|
+
option_data = self.get_boot_option(
|
|
96
|
+
system_id, option["@odata.id"].split("/")[-1]
|
|
97
|
+
)
|
|
98
|
+
boot_option_enabled = option_data.get("BootOptionEnabled", False)
|
|
99
|
+
display_name = option_data.get("DisplayName", "")
|
|
100
|
+
if "PXE" in display_name and "IPv4" in display_name and boot_option_enabled:
|
|
101
|
+
return option_data
|
|
102
|
+
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
def compute_system_reset(
|
|
106
|
+
self,
|
|
107
|
+
system_id: str,
|
|
108
|
+
reset_type: Literal[
|
|
109
|
+
"ForceRestart", "GracefulRestart", "ForceOff", "PowerCycle"
|
|
110
|
+
],
|
|
111
|
+
) -> bool:
|
|
112
|
+
token = self.create_session_token()
|
|
113
|
+
headers = {"X-Auth-Token": token}
|
|
114
|
+
response = requests.post(
|
|
115
|
+
f"https://{self.host}/redfish/v1/Systems/{system_id}/Actions/ComputerSystem.Reset",
|
|
116
|
+
json={"ResetType": reset_type},
|
|
117
|
+
headers=headers,
|
|
118
|
+
verify=False,
|
|
119
|
+
)
|
|
120
|
+
response.raise_for_status()
|
|
121
|
+
return response.status_code == 200
|
primitive/network/ui.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from rich.console import Console
|
|
2
|
+
from rich.table import Table
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def render_ports_table(ports_dict) -> None:
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
table = Table(show_header=True, header_style="bold #FFA800")
|
|
9
|
+
table.add_column("Port")
|
|
10
|
+
table.add_column("Status")
|
|
11
|
+
table.add_column("MAC Address")
|
|
12
|
+
table.add_column("IP Address")
|
|
13
|
+
|
|
14
|
+
for k, v in ports_dict.items():
|
|
15
|
+
table.add_row(
|
|
16
|
+
k, v.get("link_status"), v.get("mac_address"), v.get("ip_address")
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
console.print(table)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: primitive
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.66
|
|
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
|
|
@@ -24,6 +24,7 @@ Requires-Dist: loguru
|
|
|
24
24
|
Requires-Dist: paramiko[invoke]
|
|
25
25
|
Requires-Dist: pika>=1.3.2
|
|
26
26
|
Requires-Dist: psutil>=7.0.0
|
|
27
|
+
Requires-Dist: pyserial>=3.5
|
|
27
28
|
Requires-Dist: rich>=13.9.4
|
|
28
29
|
Requires-Dist: speedtest-cli
|
|
29
30
|
Description-Content-Type: text/markdown
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
primitive/__about__.py,sha256=
|
|
1
|
+
primitive/__about__.py,sha256=ZHOZYKO41emH20Bvp7WJ22vSZsHO5IRCfpWpII9LKbg,130
|
|
2
2
|
primitive/__init__.py,sha256=bwKdgggKNVssJFVPfKSxqFMz4IxSr54WWbmiZqTMPNI,106
|
|
3
|
-
primitive/cli.py,sha256=
|
|
4
|
-
primitive/client.py,sha256=
|
|
3
|
+
primitive/cli.py,sha256=kLjqyNijkbElbH8XhEtR6vjPc5uwOoh9mKEf2RkcfKk,2608
|
|
4
|
+
primitive/client.py,sha256=n0eQAft3lQyTT_tVE1_1BWSsh8G7gJI2kHBuXLvZVEY,3836
|
|
5
5
|
primitive/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
primitive/agent/actions.py,sha256=
|
|
6
|
+
primitive/agent/actions.py,sha256=ohY81bflsYSTsNgo2o2WP_tZr66haX4z319zf5oib-4,9362
|
|
7
7
|
primitive/agent/commands.py,sha256=o847pK7v7EWQGG67tky6a33qtwoutX6LZrP2FIS_NOk,388
|
|
8
|
-
primitive/agent/runner.py,sha256=
|
|
8
|
+
primitive/agent/runner.py,sha256=oKMCkZpeHGENLXgLIFMgOitrjIpUGYUQmcfTWwSsqSM,15598
|
|
9
9
|
primitive/agent/uploader.py,sha256=DT_Nzt5eOTm_uRcYKm1sjBBaQZzp5iNZ_uN5XktfQ30,3382
|
|
10
10
|
primitive/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
primitive/auth/actions.py,sha256=9NIEXJ1BNJutJs6AMMSjMN_ziONUAUhY_xHwojYJCLA,942
|
|
@@ -40,25 +40,30 @@ primitive/graphql/relay.py,sha256=bmij2AjdpURQ6GGVCxwWhauF-r_SxuAU2oJ4sDbLxpI,72
|
|
|
40
40
|
primitive/graphql/sdk.py,sha256=dE4TD8KiTKw3Y0uiw5XrIcuZGqexE47eSlPaPD6jDGo,1545
|
|
41
41
|
primitive/graphql/utility_fragments.py,sha256=uIjwILC4QtWNyO5vu77VjQf_p0jvP3A9q_6zRq91zqs,303
|
|
42
42
|
primitive/hardware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
primitive/hardware/actions.py,sha256=
|
|
43
|
+
primitive/hardware/actions.py,sha256=kSQ1DufDCwxY5fs3zNMj7evAunEF8vt36a7rgtjI7Uw,37323
|
|
44
44
|
primitive/hardware/android.py,sha256=tu7pBPxWFrIwb_mm5CEdFFf1_veNDOKjOCQg13i_Lh4,2758
|
|
45
|
-
primitive/hardware/commands.py,sha256=
|
|
45
|
+
primitive/hardware/commands.py,sha256=XU365RByl75ECAV_GdA4xxLrmZkwo1axlw9ZH0k3yRk,4751
|
|
46
46
|
primitive/hardware/ui.py,sha256=12rucuZ2s-w5R4bKyxON5dEbrdDnVf5sbj3K_nbdo44,2473
|
|
47
47
|
primitive/hardware/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
primitive/hardware/graphql/fragments.py,sha256=
|
|
49
|
-
primitive/hardware/graphql/mutations.py,sha256=
|
|
50
|
-
primitive/hardware/graphql/queries.py,sha256=
|
|
48
|
+
primitive/hardware/graphql/fragments.py,sha256=FRPAKB3KBfVxVm69HeYCxvvrdkW-O8CR46Inbk3wgc8,481
|
|
49
|
+
primitive/hardware/graphql/mutations.py,sha256=MqhjICTouKPgtxXy1CCyLZFa4SZbJQGk9jJMcIJDQW8,2251
|
|
50
|
+
primitive/hardware/graphql/queries.py,sha256=D7C32AKizZ_4KaqFCSffjMpnLBTnCgr5npvyrU_om-o,2099
|
|
51
51
|
primitive/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
52
|
primitive/jobs/actions.py,sha256=-IRNO7KM63cPAbGRNQycyFsugW9hAyg-TDuK0g5AiSw,6542
|
|
53
53
|
primitive/jobs/commands.py,sha256=MxPCkBEYW_eLNqgCRYeyj7ZcLOFAWfpVZlqDR2Y_S0o,830
|
|
54
54
|
primitive/jobs/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
-
primitive/jobs/graphql/fragments.py,sha256=
|
|
55
|
+
primitive/jobs/graphql/fragments.py,sha256=I-Ly0TGARt_TdenLQ7877pGLWBzono_IMj7NCzsRtYA,654
|
|
56
56
|
primitive/jobs/graphql/mutations.py,sha256=8ASvCmwQh7cMeeiykOdYaYVryG8FRIuVF6v_J8JJZuw,219
|
|
57
57
|
primitive/jobs/graphql/queries.py,sha256=57B5mSnAYjNEFFk1P69odON0fqkf7FyhsA316pcxb6g,1712
|
|
58
58
|
primitive/messaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
primitive/messaging/provider.py,sha256=
|
|
60
|
-
primitive/monitor/actions.py,sha256=
|
|
59
|
+
primitive/messaging/provider.py,sha256=NkR4hnQzEZ0SItno1TgYNvzTwgKZq03iNrnIpLK7MTg,4400
|
|
60
|
+
primitive/monitor/actions.py,sha256=GqwnTibVwAtiSU40TBexBruZI_V-7ZS8MoYZpFxq3mI,10833
|
|
61
61
|
primitive/monitor/commands.py,sha256=VDlEL_Qpm_ysHxug7VpI0cVAZ0ny6AS91Y58D7F1zkU,409
|
|
62
|
+
primitive/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
|
+
primitive/network/actions.py,sha256=qpkn9U7LTDzdoOntiFP2sBPCQYEraRjAYrkcPzhmw78,17021
|
|
64
|
+
primitive/network/commands.py,sha256=F84KmwkG0DHNLIa7Em8LMm2XDOaKMCWRpcFej8olxM0,1071
|
|
65
|
+
primitive/network/redfish.py,sha256=uOtAS_Dwc4I4bnWKNSTCQ_xsj5LTtRzW5v2P_fWaSJM,4248
|
|
66
|
+
primitive/network/ui.py,sha256=_i4lJ3hhTrPc_KS5EjXPkqqKkzdLCOdxxtk5MiDWsfU,504
|
|
62
67
|
primitive/organizations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
68
|
primitive/organizations/actions.py,sha256=kVHOhG1oS2sI5p8uldSo5L-RUZsnG36eaulVuKLyZ-M,1863
|
|
64
69
|
primitive/organizations/commands.py,sha256=_dwgVEJCqMa5VgB_7P1wLPFc0AuT1p9dtyR9JRr4kpw,487
|
|
@@ -99,8 +104,8 @@ primitive/utils/psutil.py,sha256=xa7ef435UL37jyjmUPbEqCO2ayQMpCs0HCrxVEvLcuM,763
|
|
|
99
104
|
primitive/utils/shell.py,sha256=Z4zxmOaSyGCrS0D6I436iQci-ewHLt4UxVg1CD9Serc,2171
|
|
100
105
|
primitive/utils/text.py,sha256=XiESMnlhjQ534xE2hMNf08WehE1SKaYFRNih0MmnK0k,829
|
|
101
106
|
primitive/utils/x509.py,sha256=HwHRPqakTHWd40ny-9O_yNknSL1Cxo50O0UCjXHFq04,3796
|
|
102
|
-
primitive-0.2.
|
|
103
|
-
primitive-0.2.
|
|
104
|
-
primitive-0.2.
|
|
105
|
-
primitive-0.2.
|
|
106
|
-
primitive-0.2.
|
|
107
|
+
primitive-0.2.66.dist-info/METADATA,sha256=sjynK6BDitz1RZTZyJnxC9T7Pms8jgLwHZmmdUq9Uvk,3569
|
|
108
|
+
primitive-0.2.66.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
109
|
+
primitive-0.2.66.dist-info/entry_points.txt,sha256=p1K8DMCWka5FqLlqP1sPek5Uovy9jq8u51gUsP-z334,48
|
|
110
|
+
primitive-0.2.66.dist-info/licenses/LICENSE.txt,sha256=B8kmQMJ2sxYygjCLBk770uacaMci4mPSoJJ8WoDBY_c,1098
|
|
111
|
+
primitive-0.2.66.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|