|
| 1 | +import logging |
| 2 | +from datetime import datetime |
| 3 | + |
| 4 | +from dateutil.relativedelta import relativedelta |
| 5 | +from spaceone.inventory.plugin.collector.lib import * |
| 6 | + |
| 7 | +from plugin.conf.cloud_service_conf import ICON_URL |
| 8 | +from plugin.connector.service_health.service_health_connector import ( |
| 9 | + ServiceHealthConnector, |
| 10 | +) |
| 11 | +from plugin.connector.subscriptions.subscriptions_connector import ( |
| 12 | + SubscriptionsConnector, |
| 13 | +) |
| 14 | +from plugin.manager.base import AzureBaseManager |
| 15 | + |
| 16 | +_LOGGER = logging.getLogger("spaceone") |
| 17 | + |
| 18 | + |
| 19 | +class HealthHistoryManager(AzureBaseManager): |
| 20 | + cloud_service_group = "ServiceHealth" |
| 21 | + cloud_service_type = "HealthHistory" |
| 22 | + service_code = "/Microsoft.ResourceHealth/events" |
| 23 | + |
| 24 | + def create_cloud_service(self, options: dict, secret_data: dict, schema: str): |
| 25 | + cloud_services = [] |
| 26 | + error_responses = [] |
| 27 | + |
| 28 | + external_link_format = ( |
| 29 | + "https://app.azure.com/h/{resource_id}/" |
| 30 | + + secret_data["subscription_id"][:3] |
| 31 | + + secret_data["subscription_id"][-3:] |
| 32 | + ) |
| 33 | + |
| 34 | + health_history_conn = ServiceHealthConnector(secret_data=secret_data) |
| 35 | + subscription_conn = SubscriptionsConnector(secret_data=secret_data) |
| 36 | + |
| 37 | + subscription_obj = subscription_conn.get_subscription( |
| 38 | + secret_data["subscription_id"] |
| 39 | + ) |
| 40 | + subscription_info = self.convert_nested_dictionary(subscription_obj) |
| 41 | + query_start_time = self._get_three_month_ago_date() |
| 42 | + |
| 43 | + # if not SubscriptionsConnector.region_display_map: |
| 44 | + # locations = subscription_conn.list_location_info( |
| 45 | + # secret_data["subscription_id"] |
| 46 | + # ) |
| 47 | + # SubscriptionsConnector.region_display_map = ( |
| 48 | + # self._create_region_display_map_with_locations_info(locations) |
| 49 | + # ) |
| 50 | + health_histories = health_history_conn.list_health_history(query_start_time) |
| 51 | + for health_history in health_histories: |
| 52 | + try: |
| 53 | + health_history_info = self.convert_nested_dictionary(health_history) |
| 54 | + health_history_info.update( |
| 55 | + { |
| 56 | + "tenant_id": subscription_info.get("tenant_id"), |
| 57 | + "subscription_id": subscription_info.get("subscription_id"), |
| 58 | + "subscription_name": subscription_info.get("display_name"), |
| 59 | + } |
| 60 | + ) |
| 61 | + |
| 62 | + # add impacted service info at impacted region |
| 63 | + health_history_info["impact_display"] = [] |
| 64 | + impacted_services_display = [] |
| 65 | + impacted_regions_display = [] |
| 66 | + impact_updates_display = [] |
| 67 | + impacted_subscriptions_display = [] |
| 68 | + |
| 69 | + for impact in health_history_info.get("impact", []): |
| 70 | + |
| 71 | + impacted_service = impact["impacted_service"] |
| 72 | + impacted_regions = impact.get("impacted_regions", []) |
| 73 | + |
| 74 | + impacted_services_display.append(impacted_service) |
| 75 | + for impacted_region in impacted_regions: |
| 76 | + impacted_region["impacted_service_display"] = impacted_service |
| 77 | + impacted_regions_display.append( |
| 78 | + impacted_region.get("impacted_region") |
| 79 | + ) |
| 80 | + impacted_subscriptions_display.extend( |
| 81 | + impacted_region.get("impacted_subscriptions", []) |
| 82 | + ) |
| 83 | + |
| 84 | + updates = impacted_region.get("updates") or [] |
| 85 | + impact_updates = self._create_impact_updates_display( |
| 86 | + updates, impacted_service, impacted_region |
| 87 | + ) |
| 88 | + if impact_updates: |
| 89 | + impact_updates_display.extend(impact_updates) |
| 90 | + del impacted_region["updates"] |
| 91 | + |
| 92 | + if impacted_regions: |
| 93 | + health_history_info["impact_display"].extend(impacted_regions) |
| 94 | + del impact["impacted_regions"] |
| 95 | + |
| 96 | + if impacted_services_display: |
| 97 | + health_history_info["impacted_services_display"] = list( |
| 98 | + set(impacted_services_display) |
| 99 | + ) |
| 100 | + |
| 101 | + if impacted_subscriptions_display: |
| 102 | + health_history_info["impacted_subscriptions_display"] = list( |
| 103 | + set(impacted_subscriptions_display) |
| 104 | + ) |
| 105 | + |
| 106 | + if impacted_regions_display: |
| 107 | + health_history_info["impacted_regions_display"] = list( |
| 108 | + set(impacted_regions_display) |
| 109 | + ) |
| 110 | + |
| 111 | + if impact_updates_display: |
| 112 | + health_history_info["impact_updates_display"] = ( |
| 113 | + impact_updates_display |
| 114 | + ) |
| 115 | + |
| 116 | + if len(impacted_regions_display) > 1: |
| 117 | + region = "Multi Regions" |
| 118 | + else: |
| 119 | + region = impacted_regions_display[0] |
| 120 | + |
| 121 | + cloud_services.append( |
| 122 | + make_cloud_service( |
| 123 | + name=health_history_info.get("title"), |
| 124 | + account=secret_data["subscription_id"], |
| 125 | + cloud_service_type=self.cloud_service_type, |
| 126 | + cloud_service_group=self.cloud_service_group, |
| 127 | + provider=self.provider, |
| 128 | + region_code=region, |
| 129 | + data=health_history_info, |
| 130 | + reference=self.make_reference( |
| 131 | + health_history_info.get("id"), external_link_format |
| 132 | + ), |
| 133 | + data_format="dict", |
| 134 | + ) |
| 135 | + ) |
| 136 | + except Exception as e: |
| 137 | + _LOGGER.error(f"[create_cloud_service] Error {self.service} {e}") |
| 138 | + error_responses.append( |
| 139 | + make_error_response( |
| 140 | + error=e, |
| 141 | + provider=self.provider, |
| 142 | + cloud_service_group=self.cloud_service_group, |
| 143 | + cloud_service_type=self.cloud_service_type, |
| 144 | + ) |
| 145 | + ) |
| 146 | + |
| 147 | + return cloud_services, error_responses |
| 148 | + |
| 149 | + def create_cloud_service_type(self): |
| 150 | + return make_cloud_service_type( |
| 151 | + name=self.cloud_service_type, |
| 152 | + group=self.cloud_service_group, |
| 153 | + provider=self.provider, |
| 154 | + service_code=self.service_code, |
| 155 | + metadata_path=self.get_metadata_path(), |
| 156 | + is_primary=True, |
| 157 | + is_major=True, |
| 158 | + labels=["Management"], |
| 159 | + tags={"spaceone:icon": f"{ICON_URL}/azure-service-health.svg"}, |
| 160 | + ) |
| 161 | + |
| 162 | + @staticmethod |
| 163 | + def _create_impact_updates_display( |
| 164 | + updates: list, impacted_service: str, impacted_region: dict |
| 165 | + ) -> list: |
| 166 | + impact_updates_display = [] |
| 167 | + for update in updates: |
| 168 | + update.update( |
| 169 | + { |
| 170 | + "impacted_service_display": impacted_service, |
| 171 | + "impacted_region_display": impacted_region.get("impacted_region"), |
| 172 | + } |
| 173 | + ) |
| 174 | + impact_updates_display.append(update) |
| 175 | + return impact_updates_display |
| 176 | + |
| 177 | + @staticmethod |
| 178 | + def _get_three_month_ago_date() -> str: |
| 179 | + current_date = datetime.utcnow() |
| 180 | + three_months_ago_date = current_date - relativedelta(months=3) |
| 181 | + first_day_three_months_ago = three_months_ago_date.replace(day=1) |
| 182 | + return first_day_three_months_ago.strftime("%Y/%m/%d") |
| 183 | + |
| 184 | + def _create_region_display_map_with_locations_info(self, locations) -> dict: |
| 185 | + region_display_map = {} |
| 186 | + for location in locations: |
| 187 | + location_info = self.convert_nested_dictionary(location) |
| 188 | + display_name = location_info.get("display_name") |
| 189 | + region_name = location_info.get("name") |
| 190 | + region_display_map[display_name] = region_name |
| 191 | + return region_display_map |
0 commit comments