def build_schedule_from_maintenance_window(period_str): """ Builds a Instance running schedule based on an RDS preferred maintenance windows string in format ddd:hh:mm-ddd:hh:mm :param period_str: rds maintenance windows string :return: Instance running schedule with timezone UTC """ # get elements of period start_string, stop_string = period_str.split("-") start_day_string, start_hhmm_string = start_string.split(":", 1) stop_day_string, stop_hhmm_string = stop_string.split(":", 1) # weekday set builder weekdays_builder = WeekdaySetBuilder() start_weekday = weekdays_builder.build(start_day_string) start_time = SchedulerConfigBuilder.get_time_from_string(start_hhmm_string) end_time = SchedulerConfigBuilder.get_time_from_string(stop_hhmm_string) # windows with now day overlap, can do with one period for schedule if start_day_string == stop_day_string: periods = [ { "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME, begintime=start_time, endtime=end_time, weekdays=start_weekday) }] else: # window with day overlap, need two periods for schedule end_time_day1 = SchedulerConfigBuilder.get_time_from_string("23:59") begin_time_day2 = SchedulerConfigBuilder.get_time_from_string("00:00") stop_weekday = weekdays_builder.build(stop_day_string) periods = [ { "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME + "-{}".format(start_day_string), begintime=start_time, endtime=end_time_day1, weekdays=start_weekday), "instancetype": None }, { "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME + "-{}".format(stop_day_string), begintime=begin_time_day2, endtime=end_time, weekdays=stop_weekday), "instancetype": None }] # create schedule with period(s) and timezone UTC schedule = InstanceSchedule(name=MAINTENANCE_SCHEDULE_NAME, periods=periods, timezone="UTC", enforced=True) return schedule
def _build_period(cls, period_configuration, dt): def get_periodname(config): period_name = config.get(configuration.NAME) if not period_name: raise ValueError(MSG_NAME_MISSING_IN_PERIOD.format(config)) return period_name # reads a start and end time from config def get_begin_and_end(period_name, config): begin = SchedulerConfigBuilder.get_time_from_string( config.get(configuration.BEGINTIME)) end = SchedulerConfigBuilder.get_time_from_string( config.get(configuration.ENDTIME)) if (begin and end) and begin > end: raise ValueError( MSG_BEGIN_MUST_BEFORE_END.format(begin, end, period_name)) return begin, end def build_period_config_set(period_config, set_builder, config_name): config_set = period_config.get(config_name) if config_set: return set_builder.build(config_set) else: return None name = get_periodname(period_configuration) begin_time, end_time = get_begin_and_end(name, period_configuration) week_days = build_period_config_set( period_configuration, WeekdaySetBuilder(year=dt.year, month=dt.month, day=dt.day), configuration.WEEKDAYS) months = build_period_config_set(period_configuration, MonthSetBuilder(), configuration.MONTHS) monthdays = build_period_config_set( period_configuration, MonthdaySetBuilder(year=dt.year, month=dt.month), configuration.MONTHDAYS) return RunningPeriod(name=name, begintime=begin_time, endtime=end_time, weekdays=week_days, months=months, monthdays=monthdays)
def _schedule_from_maint_window(self, name, start, hours, interval): start_dt = start.replace(second=0, microsecond=0) start_before_begin = min(interval, 10) begin_dt = start_dt - timedelta(minutes=start_before_begin) end_dt = start_dt + timedelta(hours=hours) if begin_dt.day == end_dt.day: periods = [{ "period": RunningPeriod(name="{}-period".format(name), begintime=begin_dt.time(), endtime=end_dt.time(), monthdays={begin_dt.day}, months={begin_dt.month}), "instancetype": None }] elif end_dt - begin_dt <= timedelta(hours=24): periods = [{ "period": RunningPeriod( name="{}-period-1".format(name), begintime=begin_dt.time(), endtime=SchedulerConfigBuilder.get_time_from_string( "23:59"), monthdays={begin_dt.day}, months={begin_dt.month}), "instancetype": None }, { "period": RunningPeriod( name="{}-period-2".format(name), begintime=SchedulerConfigBuilder.get_time_from_string( "00:00"), endtime=end_dt.time(), monthdays={end_dt.day}, months={end_dt.month}), "instancetype": None }] else: periods = [{ "period": RunningPeriod( name="{}-period-1".format(name), begintime=begin_dt.time(), endtime=SchedulerConfigBuilder.get_time_from_string( "23:59"), monthdays={begin_dt.day}, months={begin_dt.month}), "instancetype": None }, { "period": RunningPeriod(name="{}-period-2".format(name), monthdays={(end_dt - timedelta(days=1)).day}, months={(end_dt - timedelta(days=1)).month}), "instancetype": None }, { "period": RunningPeriod( name="{}-period-3".format(name), begintime=SchedulerConfigBuilder.get_time_from_string( "00:00"), endtime=end_dt.time(), monthdays={end_dt.day}, months={end_dt.month}), "instancetype": None }] schedule = InstanceSchedule( name=name, timezone="UTC", description="{} maintenance window".format(name), enforced=True, periods=periods) self._logger.info(INF_MAINT_WINDOW, name, begin_dt.isoformat(), end_dt.isoformat()) return schedule
def configuration_from_dict(d): """ This method builds a configuration object instance that is passed as a dictionary in the event of a lambda function :param d: :return: """ config_args = {} for attr in [ ATTR_TAGNAME, ATTR_DEFAULT_TIMEZONE, ATTR_TRACE, ATTR_ENABLE_SSM_MAINTENANCE_WINDOWS, ATTR_SCHEDULE_CLUSTERS, ATTR_CREATE_RDS_SNAPSHOT, ATTR_USE_METRICS, ATTR_SCHEDULE_LAMBDA_ACCOUNT, ATTR_STARTED_TAGS, ATTR_STOPPED_TAGS ]: config_args[attr] = d.get(attr, None) for attr in [ ATTR_REGIONS, ATTR_CROSS_ACCOUNT_ROLES, ATTR_SCHEDULED_SERVICES ]: config_args[attr] = set(d.get(attr, [])) periods = {} for period_name in d.get(ATTR_PERIODS, {}): period_data = d[ATTR_PERIODS][period_name] period_args = {ATTR_NAME: period_name} for attr in [ATTR_BEGINTIME, ATTR_ENDTIME]: if attr in period_data: period_args[ attr] = SchedulerConfigBuilder.get_time_from_string( period_data[attr]) for attr in [ATTR_WEEKDAYS, ATTR_MONTHDAYS, ATTR_MONTHS]: if attr in period_data: period_args[attr] = set(period_data.get(attr, None)) period = RunningPeriod(**period_args) periods[period_name] = period config_args[ATTR_SCHEDULES] = {} for schedule_name in d.get(ATTR_SCHEDULES, {}): schedule_args = {} schedule_data = d[ATTR_SCHEDULES][schedule_name] for attr in [ ATTR_NAME, ATTR_TIMEZONE, ATTR_OVERRIDE_STATUS, ATTR_STOP_NEW_INSTANCES, ATTR_USE_METRICS, ATTR_ENFORCED, ATTR_HIBERNATE, ATTR_RETAIN_RUNNING, ATTR_SSM_MAINTENANCE_WINDOW, ATTR_USE_MAINTENANCE_WINDOW ]: schedule_args[attr] = schedule_data.get(attr, None) for attr in [ATTR_SCHEDULE_DT]: if attr in schedule_data: schedule_args[attr] = dateutil.parser.parse( schedule_data[attr]) if schedule_args[ATTR_OVERRIDE_STATUS] is None: schedule_args[ATTR_PERIODS] = [] for period in schedule_data.get(ATTR_PERIODS): temp = period.split(configuration.INSTANCE_TYPE_SEP) if len(temp) > 1: name = temp[0] instance_type = temp[1] else: name = period instance_type = None schedule_args[ATTR_PERIODS].append({ ATTR_PERIOD: periods[name], ATTR_INSTANCE_TYPE: instance_type }) schedule = InstanceSchedule(**schedule_args) config_args[ATTR_SCHEDULES][schedule_name] = schedule config = SchedulerConfig(**config_args) return config