primitive 0.2.66__tar.gz → 0.2.68__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.66 → primitive-0.2.68}/PKG-INFO +1 -1
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/__about__.py +1 -1
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/agent/runner.py +14 -4
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/actions.py +36 -0
- primitive-0.2.68/src/primitive/network/ssh.py +94 -0
- {primitive-0.2.66 → primitive-0.2.68}/.git-hooks/pre-commit +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.gitattributes +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.github/workflows/lint.yml +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.github/workflows/publish.yml +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.github/workflows/pyright.yml +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.gitignore +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.vscode/extensions.json +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/.vscode/settings.json +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/LICENSE.txt +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/Makefile +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/README.md +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/linux setup.md +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/pyproject.toml +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/agent/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/agent/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/agent/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/agent/uploader.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/auth/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/auth/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/auth/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/auth/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/auth/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/cli.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/client.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/launch_agents.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/launch_service.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/daemons/ui.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/exec/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/exec/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/exec/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/exec/interactive.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/files/ui.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/git/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/git/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/git/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/git/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/git/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/graphql/relay.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/graphql/sdk.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/graphql/utility_fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/android.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/hardware/ui.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/jobs/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/messaging/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/messaging/provider.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/monitor/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/monitor/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/network/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/network/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/network/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/network/redfish.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/network/ui.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/organizations/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/projects/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/provisioning/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/provisioning/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/provisioning/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/provisioning/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/commands.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/graphql/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/graphql/fragments.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/graphql/mutations.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/reservations/graphql/queries.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/actions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/auth.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/cache.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/chunk_size.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/config.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/daemons.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/exceptions.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/logging.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/memory_size.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/printer.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/psutil.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/shell.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/text.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/src/primitive/utils/x509.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/tests/__init__.py +0 -0
- {primitive-0.2.66 → primitive-0.2.68}/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.68
|
|
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
|
|
@@ -9,6 +9,7 @@ from datetime import datetime, timezone
|
|
|
9
9
|
|
|
10
10
|
from loguru import logger
|
|
11
11
|
|
|
12
|
+
from primitive.network.ssh import wait_for_ssh
|
|
12
13
|
from primitive.utils.cache import get_artifacts_cache, get_logs_cache, get_sources_cache
|
|
13
14
|
from primitive.utils.logging import fmt, log_context
|
|
14
15
|
from primitive.utils.psutil import kill_process_and_children
|
|
@@ -231,6 +232,7 @@ class Runner:
|
|
|
231
232
|
|
|
232
233
|
for i, cmd in enumerate(commands):
|
|
233
234
|
if cmd == "oobpowercycle":
|
|
235
|
+
logger.info("Performing out-of-band power cycle")
|
|
234
236
|
from primitive.network.redfish import RedfishClient
|
|
235
237
|
|
|
236
238
|
bmc_host = self.target_hardware_secret.get("bmcHostname", None)
|
|
@@ -253,15 +255,16 @@ class Runner:
|
|
|
253
255
|
)
|
|
254
256
|
redfish.compute_system_reset(system_id="1", reset_type="ForceRestart")
|
|
255
257
|
if self.target_hardware_id:
|
|
256
|
-
self.primitive.hardware.
|
|
258
|
+
await self.primitive.hardware.aupdate_hardware(
|
|
257
259
|
hardware_id=self.target_hardware_id,
|
|
258
260
|
is_online=False,
|
|
259
261
|
is_rebooting=True,
|
|
260
|
-
start_rebooting_at=datetime.now(timezone.utc),
|
|
262
|
+
start_rebooting_at=str(datetime.now(timezone.utc)),
|
|
261
263
|
)
|
|
262
264
|
continue
|
|
263
265
|
|
|
264
266
|
if cmd == "pxeboot":
|
|
267
|
+
logger.info("Setting next boot to PXE and rebooting")
|
|
265
268
|
from primitive.network.redfish import RedfishClient
|
|
266
269
|
|
|
267
270
|
bmc_host = self.target_hardware_secret.get("bmcHostname", None)
|
|
@@ -290,12 +293,19 @@ class Runner:
|
|
|
290
293
|
)
|
|
291
294
|
redfish.compute_system_reset(system_id="1", reset_type="ForceRestart")
|
|
292
295
|
if self.target_hardware_id:
|
|
293
|
-
self.primitive.hardware.
|
|
296
|
+
await self.primitive.hardware.aupdate_hardware(
|
|
294
297
|
hardware_id=self.target_hardware_id,
|
|
295
298
|
is_online=False,
|
|
296
299
|
is_rebooting=True,
|
|
297
|
-
start_rebooting_at=datetime.now(timezone.utc),
|
|
300
|
+
start_rebooting_at=str(datetime.now(timezone.utc)),
|
|
298
301
|
)
|
|
302
|
+
wait_for_ssh(
|
|
303
|
+
hostname=self.target_hardware_secret.get("hostname"),
|
|
304
|
+
username=self.target_hardware_secret.get("username"),
|
|
305
|
+
password=self.target_hardware_secret.get("password"),
|
|
306
|
+
port=22,
|
|
307
|
+
)
|
|
308
|
+
logger.info("PXE boot successful, SSH is now available")
|
|
299
309
|
continue
|
|
300
310
|
|
|
301
311
|
args = ["/bin/bash", "-c", cmd]
|
|
@@ -981,3 +981,39 @@ class Hardware(BaseAction):
|
|
|
981
981
|
logger.info(message)
|
|
982
982
|
|
|
983
983
|
return result
|
|
984
|
+
|
|
985
|
+
@guard
|
|
986
|
+
async def aupdate_hardware(
|
|
987
|
+
self,
|
|
988
|
+
hardware_id: str,
|
|
989
|
+
is_online: Optional[bool] = None,
|
|
990
|
+
is_rebooting: Optional[bool] = None,
|
|
991
|
+
start_rebooting_at: Optional[str] = None,
|
|
992
|
+
):
|
|
993
|
+
new_state: dict = {
|
|
994
|
+
"id": hardware_id,
|
|
995
|
+
}
|
|
996
|
+
if is_online is not None:
|
|
997
|
+
new_state["isOnline"] = is_online
|
|
998
|
+
if is_rebooting is not None:
|
|
999
|
+
new_state["isRebooting"] = is_rebooting
|
|
1000
|
+
if start_rebooting_at is not None:
|
|
1001
|
+
new_state["startRebootingAt"] = start_rebooting_at
|
|
1002
|
+
|
|
1003
|
+
mutation = gql(hardware_update_mutation)
|
|
1004
|
+
|
|
1005
|
+
input = new_state
|
|
1006
|
+
variables = {"input": input}
|
|
1007
|
+
try:
|
|
1008
|
+
result = await self.primitive.session.execute_async(
|
|
1009
|
+
mutation, variable_values=variables, get_execution_result=True
|
|
1010
|
+
)
|
|
1011
|
+
except client_exceptions.ClientConnectorError as exception:
|
|
1012
|
+
message = "Failed to update hardware! "
|
|
1013
|
+
logger.exception(message)
|
|
1014
|
+
raise exception
|
|
1015
|
+
|
|
1016
|
+
message = "Updated hardware successfully! "
|
|
1017
|
+
logger.info(message)
|
|
1018
|
+
|
|
1019
|
+
return result
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import paramiko
|
|
2
|
+
import socket
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_ssh_connection(hostname, username, password=None, key_filename=None, port=22):
|
|
7
|
+
"""
|
|
8
|
+
Tests an SSH connection to a remote host.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
hostname (str): The hostname or IP address of the remote SSH server.
|
|
12
|
+
username (str): The username for authentication.
|
|
13
|
+
password (str, optional): The password for authentication. Defaults to None.
|
|
14
|
+
key_filename (str, optional): Path to the private key file for authentication. Defaults to None.
|
|
15
|
+
port (int, optional): The SSH port. Defaults to 22.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
bool: True if the connection is successful, False otherwise.
|
|
19
|
+
"""
|
|
20
|
+
ssh_client = paramiko.SSHClient()
|
|
21
|
+
ssh_client.set_missing_host_key_policy(
|
|
22
|
+
paramiko.AutoAddPolicy()
|
|
23
|
+
) # Auto-add new host keys
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
if password:
|
|
27
|
+
ssh_client.connect(
|
|
28
|
+
hostname=hostname, port=port, username=username, password=password
|
|
29
|
+
)
|
|
30
|
+
elif key_filename:
|
|
31
|
+
ssh_client.connect(
|
|
32
|
+
hostname=hostname,
|
|
33
|
+
port=port,
|
|
34
|
+
username=username,
|
|
35
|
+
key_filename=key_filename,
|
|
36
|
+
)
|
|
37
|
+
else:
|
|
38
|
+
print(
|
|
39
|
+
"Error: Either password or key_filename must be provided for authentication."
|
|
40
|
+
)
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
print(f"Successfully connected to {hostname} as {username}")
|
|
44
|
+
return True
|
|
45
|
+
except paramiko.AuthenticationException:
|
|
46
|
+
print(f"Authentication failed for {username} on {hostname}")
|
|
47
|
+
return False
|
|
48
|
+
except paramiko.SSHException as e:
|
|
49
|
+
print(f"SSH error connecting to {hostname}: {e}")
|
|
50
|
+
return False
|
|
51
|
+
except socket.error as e:
|
|
52
|
+
print(f"Socket error connecting to {hostname}: {e}")
|
|
53
|
+
return False
|
|
54
|
+
except Exception as e:
|
|
55
|
+
print(f"An unexpected error occurred: {e}")
|
|
56
|
+
return False
|
|
57
|
+
finally:
|
|
58
|
+
ssh_client.close()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
TEN_MINUTES = 60 * 10
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def wait_for_ssh(
|
|
65
|
+
hostname, username, password=None, key_filename=None, port=22, timeout=TEN_MINUTES
|
|
66
|
+
):
|
|
67
|
+
"""
|
|
68
|
+
Waits until an SSH connection to a remote host can be established.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
hostname (str): The hostname or IP address of the remote SSH server.
|
|
72
|
+
username (str): The username for authentication.
|
|
73
|
+
password (str, optional): The password for authentication. Defaults to None.
|
|
74
|
+
key_filename (str, optional): Path to the private key file for authentication. Defaults to None.
|
|
75
|
+
port (int, optional): The SSH port. Defaults to 22.
|
|
76
|
+
timeout (int, optional): Maximum time to wait in seconds. Defaults to 300.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
bool: True if the connection is successful within the timeout, False otherwise.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
start_time = time.time()
|
|
83
|
+
while time.time() - start_time < timeout:
|
|
84
|
+
if test_ssh_connection(
|
|
85
|
+
hostname, username, password=password, key_filename=key_filename, port=port
|
|
86
|
+
):
|
|
87
|
+
return True
|
|
88
|
+
print(f"Waiting for SSH to become available on {hostname}...")
|
|
89
|
+
time.sleep(10)
|
|
90
|
+
|
|
91
|
+
print(
|
|
92
|
+
f"Timeout reached: Unable to connect to {hostname} via SSH within {timeout} seconds."
|
|
93
|
+
)
|
|
94
|
+
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|