コード例 #1
0
    def load_event_definitions(self):
        self.scheduler_table.reread_table()
        self.events = self.scheduler_table.get_dict()
        for e in self.events:
            if not isinstance(self.events[e], str): continue

            digest = misc.sha256("%s:%s" % (e, self.events[e]))
            event_name = "CS-Cron-%s%s-%s" % (self.context["GroupName"],
                                              self.context["VariantNumber"],
                                              digest[:10])
            try:
                self.event_names.append({
                    "Name":
                    event_name,
                    "EventName":
                    e,
                    "Event":
                    self.events[e],
                    "Data":
                    misc.parse_line_as_list_of_dict(self.events[e],
                                                    leading_keyname="schedule")
                })
            except Exception as ex:
                log.exception(
                    "Failed to parse Scheduler event '%s' (%s) : %s" %
                    (e, self.events[e], ex))
コード例 #2
0
    def is_maintenance_time(self, fleet=None, meta=None):
        if not self.is_feature_enabled("maintenance_window"):
            return False
        now         = self.context["now"]
        sa          = max(Cfg.get_duration_secs("ssm.feature.maintenance_window.start_ahead"), 30)
        # We compute a predictive jitter to avoid all subleets starting exactly at the same time
        group_name  = self.context["GroupName"]
        jitter_salt = int(misc.sha256(f"{group_name}:{fleet}")[:3], 16) / (16 * 16 * 16) * sa
        jitter      = Cfg.get_abs_or_percent("ssm.feature.maintenance_window.start_ahead.max_jitter", 0, jitter_salt)

        start_ahead = timedelta(seconds=(sa-jitter))
        windows     = copy.deepcopy(self._get_maintenance_windows_for_fleet(fleet=fleet))
        for w in windows:
            window_id= w["WindowId"]
            if "NextExecutionTime" in w:
                end_time = w["NextExecutionTime"] + timedelta(hours=int(w["Duration"]))
                if now >= (w["NextExecutionTime"] - start_ahead) and now < end_time:
                    # We are entering a new maintenance window period. Remember it...
                    self.o_state.set_state(f"ssm.events.maintenance_window.last_next_execution_time.{window_id}", 
                        w["NextExecutionTime"], TTL=self.ttl)
                    self.o_state.set_state(f"ssm.events.maintenance_window.last_next_execution_duration.{window_id}", 
                        w["Duration"], TTL=self.ttl)
                w["_FutureNextExecutionTime"] = w["NextExecutionTime"]
            # SSM maintenance windows do not always have a NextExecutionTime field -=OR=- it contains the future
            #  NextExecutionTime of the next iteration. In both case, we westore it from a backuped one.
            next_execution_time = self.o_state.get_state_date(f"ssm.events.maintenance_window.last_next_execution_time.{window_id}", TTL=self.ttl)
            if next_execution_time is not None:
                w["NextExecutionTime"] = next_execution_time
            if "Duration" not in w:
                next_execution_duration = self.o_state.get_state(f"ssm.events.maintenance_window.last_next_execution_duration.{window_id}", TTL=self.ttl)
                if next_execution_duration is not None:
                    w["Duration"] = next_execution_duration

        valid_windows = [w for w in windows if "NextExecutionTime" in w and "Duration" in w]
        fleetname     = "Main" if fleet is None else fleet
        next_window   = None
        for w in sorted(valid_windows, key=lambda w: w["NextExecutionTime"]):
            end_time   = w["NextExecutionTime"] + timedelta(hours=int(w["Duration"]))
            start_time = w["NextExecutionTime"] - start_ahead
            if now >= start_time and now < end_time:
                if meta is not None: 
                    meta["MatchingWindow"] = w
                    meta["MatchingWindowMessage"] = f"Found ACTIVE matching window for fleet {fleetname} : {w}"
                    meta["StartTime"] = w["NextExecutionTime"]
                    meta["EndTime"] = end_time
                return True
            if ("_FutureNextExecutionTime" in w and w["_FutureNextExecutionTime"] > now and 
                    (next_window is None or w["_FutureNextExecutionTime"] < next_window["_FutureNextExecutionTime"])):
                next_window     = w
        if next_window is not None and meta is not None:
            meta["NextWindowMessage"] = (f"Next SSM Maintenance Window for {fleetname} fleet is '%s/%s in %s "
                f"(Fleet will start ahead at %s)." % (w["WindowId"], w["Name"], (w["_FutureNextExecutionTime"] - now), 
                    w["_FutureNextExecutionTime"] - start_ahead))
        return False
コード例 #3
0
 def call_sqs(self, arn, region, account_id, service_path, content, e):
     misc.initialize_clients(["sqs"], self.context)
     client = self.context["sqs.client"]
     response = client.get_queue_url(
         QueueName=service_path,
         QueueOwnerAWSAccountId=account_id
     )
     log.info("Notifying to SQS Queue '%s' for event '%s'..." % (arn, e))
     args = {
             "QueueUrl": response["QueueUrl"],
             "MessageBody": content
         }
     if service_path.endswith(".fifo"):
         # create a message group id that is unique to this CS deployment to allow
         # SQS FIFO sharing between multiple deployment concurrently.
         args["MessageGroupId"] = f"CS-notif-channel-{account_id}-%s" % (self.context["GroupName"])
         args["MessageDeduplicationId"] = misc.sha256(content)
     response = client.send_message(**args)
コード例 #4
0
 def _format_query(query, metric_id, metric):
     uniq_id = "id%s" % misc.sha256(metric_id)
     query["IdMapping"][uniq_id] = metric_id
     q = {
         "Id": uniq_id,
         "MetricStat": {
             "Metric": {
                 "MetricName": metric["MetricName"],
                 "Namespace": metric["Namespace"]
             },
             "Period": metric["Period"],
             "Stat": metric["Statistic"]
         },
         "ReturnData": True
     }
     if "Dimensions" in metric:
         q["MetricStat"]["Metric"]["Dimensions"] = metric["Dimensions"]
     if "Unit" in metric: q["MetricStat"]["Unit"] = metric["Unit"]
     query["Queries"].append(q)