|
8 | 8 | import json |
9 | 9 | import os |
10 | 10 | import pprint |
| 11 | +from datetime import datetime, timezone |
11 | 12 | from typing import Any, Dict, List |
12 | 13 |
|
13 | 14 | import boto3 |
@@ -446,6 +447,75 @@ def check_licenses(self) -> Dict[str, Any]: |
446 | 447 |
|
447 | 448 | return response_dict |
448 | 449 |
|
| 450 | + def get_machine_sync_details(self) -> List[Any]: |
| 451 | + """Checks CloudEndure Project inventory and returns register machine's |
| 452 | + replication state. |
| 453 | + """ |
| 454 | + response_list: List[Any] = [] |
| 455 | + print(f"INFO: Retreiving sync status for all machines in Project: ({self.project_name})") |
| 456 | + machines_response: Response = self.api.api_call(f"projects/{self.project_id}/machines") |
| 457 | + if not machines_response.ok: |
| 458 | + print(f"ERROR: API response did not return a 2XX status; Returned {machines_response.status_code} ...") |
| 459 | + return {} |
| 460 | + ce_project_inventory = json.loads(machines_response.text).get("items", []) |
| 461 | + for _query_value in ce_project_inventory: |
| 462 | + machine_name: str = _query_value["sourceProperties"]["name"] |
| 463 | + sync_details: Dict[str, Any] = { |
| 464 | + "machine_name": machine_name, |
| 465 | + "in_inventory": _query_value["isAgentInstalled"], |
| 466 | + "replication_status": _query_value["replicationStatus"], |
| 467 | + "last_seen_utc": _query_value["replicationInfo"]["lastSeenDateTime"], |
| 468 | + "total_storage_bytes": _query_value["replicationInfo"]["totalStorageBytes"], |
| 469 | + "replicated_storage_bytes": _query_value["replicationInfo"]["replicatedStorageBytes"], |
| 470 | + "rescanned_storage_bytes": 0, |
| 471 | + "backlogged_storage_bytes": _query_value["replicationInfo"]["backloggedStorageBytes"], |
| 472 | + } |
| 473 | + if "rescannedStorageBytes" in _query_value["replicationInfo"]: |
| 474 | + sync_details["recanned_storage_bytes"] = _query_value["replicationInfo"]["rescannedStorageBytes"] |
| 475 | + response_list.append(sync_details) |
| 476 | + # Project is still printing to console as a convention; Emitting an |
| 477 | + # output to stdout for interactive usage |
| 478 | + return response_list |
| 479 | + |
| 480 | + def inspect_ce_project(self, check_type: str) -> List[Any]: |
| 481 | + if not check_type: |
| 482 | + print( |
| 483 | + f"ERROR: Unknown check_type of '{check_type}'; Please use 'not_synced', 'not_started', or 'not_current' ..." |
| 484 | + ) |
| 485 | + return |
| 486 | + result: List[Any] = [] |
| 487 | + sync_report: List[Any] = self.get_machine_sync_details() |
| 488 | + print(f"INFO: Using check '{check_type}' on Project: ({self.project_name})") |
| 489 | + inspector = getattr(self, check_type) |
| 490 | + for item in sync_report: |
| 491 | + mcheck = inspector(machine=item) |
| 492 | + if mcheck: |
| 493 | + result.append(item) |
| 494 | + print(f"INFO: Check '{check_type}' completed; {len(result)} machines matched in Project: ({self.project_name})") |
| 495 | + return result |
| 496 | + |
| 497 | + def not_synced(self, machine) -> bool: |
| 498 | + if machine["backlogged_storage_bytes"] > 0 or machine["rescanned_storage_bytes"] > 0: |
| 499 | + return True |
| 500 | + else: |
| 501 | + return False |
| 502 | + |
| 503 | + def not_started(self, machine) -> bool: |
| 504 | + if machine["replication_status"] == "STARTED": |
| 505 | + return False |
| 506 | + else: |
| 507 | + return True |
| 508 | + |
| 509 | + def not_current(self, machine, delta_seconds: int = 86400) -> bool: |
| 510 | + now: datetime = datetime.now(timezone.utc) |
| 511 | + machine_last_seen: datetime = datetime.fromisoformat(machine["last_seen_utc"]) |
| 512 | + last_seen_delta: datetime = now - machine_last_seen |
| 513 | + # If you're exceeding the size of int, you have bigger problems |
| 514 | + if int(last_seen_delta.total_seconds()) >= delta_seconds: |
| 515 | + return True |
| 516 | + else: |
| 517 | + return False |
| 518 | + |
449 | 519 | def update_blueprint(self) -> bool: |
450 | 520 | """Update the blueprint associated with the specified machines.""" |
451 | 521 | print(f"Updating CloudEndure Blueprints - Name: ({self.project_name}) - Dry Run: ({self.dry_run})") |
|
0 commit comments