Beispiel #1
0
def autoscale_profile_create(client,
                             autoscale_name,
                             resource_group_name,
                             profile_name,
                             count,
                             timezone,
                             start=None,
                             end=None,
                             copy_rules=None,
                             min_count=None,
                             max_count=None,
                             recurrence=None):
    from azure.mgmt.monitor.models import ScaleCapacity
    autoscale_settings = client.get(resource_group_name, autoscale_name)
    capacity = ScaleCapacity(default=count,
                             minimum=min_count or count,
                             maximum=max_count or count)
    if recurrence:
        _create_recurring_profile(autoscale_settings, profile_name, start, end,
                                  recurrence, capacity, copy_rules, timezone)
    else:
        _create_fixed_profile(autoscale_settings, profile_name, start, end,
                              capacity, copy_rules, timezone)
    autoscale_settings = client.create_or_update(resource_group_name,
                                                 autoscale_name,
                                                 autoscale_settings)
    profile = next(x for x in autoscale_settings.profiles
                   if x.name == profile_name)
    return profile
Beispiel #2
0
def autoscale_create(client,
                     resource,
                     count,
                     autoscale_name=None,
                     resource_group_name=None,
                     min_count=None,
                     max_count=None,
                     location=None,
                     tags=None,
                     disabled=None,
                     actions=None,
                     email_administrator=None,
                     email_coadministrators=None):

    from azure.mgmt.monitor.models import (AutoscaleSettingResource,
                                           AutoscaleProfile,
                                           AutoscaleNotification,
                                           ScaleCapacity, EmailNotification,
                                           WebhookNotification)
    if not autoscale_name:
        from msrestazure.tools import parse_resource_id
        autoscale_name = parse_resource_id(resource)['name']
    min_count = min_count or count
    max_count = max_count or count
    default_profile = AutoscaleProfile(name=DEFAULT_PROFILE_NAME,
                                       capacity=ScaleCapacity(
                                           default=count,
                                           minimum=min_count,
                                           maximum=max_count),
                                       rules=[])
    notification = AutoscaleNotification(email=EmailNotification(
        custom_emails=[],
        send_to_subscription_administrator=email_administrator,
        send_to_subscription_co_administrators=email_coadministrators),
                                         webhooks=[])
    for action in actions or []:
        if isinstance(action, EmailNotification):
            for email in action.custom_emails:
                notification.email.custom_emails.append(email)
        elif isinstance(action, WebhookNotification):
            notification.webhooks.append(action)
    autoscale = AutoscaleSettingResource(
        location=location,
        profiles=[default_profile],
        tags=tags,
        notifications=[notification],
        enabled=not disabled,
        autoscale_setting_resource_name=autoscale_name,
        target_resource_uri=resource)
    if not (min_count == count and max_count == count):
        logger.warning(
            'Follow up with `az monitor autoscale rule create` to add scaling rules.'
        )
    return client.create_or_update(resource_group_name, autoscale_name,
                                   autoscale)
Beispiel #3
0
    def exec_module(self, **kwargs):

        for key in list(self.module_arg_spec.keys()) + ['tags']:
            setattr(self, key, kwargs[key])

        results = None
        changed = False

        self.log('Fetching auto scale settings {0}'.format(self.name))
        results = self.get_auto_scale()
        if results and self.state == 'absent':
            # delete
            changed = True
            if not self.check_mode:
                self.delete_auto_scale()
        elif self.state == 'present':

            if not self.location:
                # Set default location
                resource_group = self.get_resource_group(self.resource_group)
                self.location = resource_group.location

            resource_id = self.target
            if isinstance(self.target, dict):
                resource_id = format_resource_id(
                    val=self.target['name'],
                    subscription_id=self.target.get('subscription_id')
                    or self.subscription_id,
                    namespace=self.target['namespace'],
                    types=self.target['types'],
                    resource_group=self.target.get('resource_group')
                    or self.resource_group)
            self.target = resource_id
            resource_name = self.name

            def create_rule_instance(params):
                rule = params.copy()
                rule['metric_resource_uri'] = rule.get('metric_resource_uri',
                                                       self.target)
                rule['time_grain'] = timedelta(
                    minutes=rule.get('time_grain', 0))
                rule['time_window'] = timedelta(
                    minutes=rule.get('time_window', 0))
                rule['cooldown'] = timedelta(minutes=rule.get('cooldown', 0))
                return ScaleRule(metric_trigger=MetricTrigger(**rule),
                                 scale_action=ScaleAction(**rule))

            profiles = [
                AutoscaleProfile(
                    name=p.get('name'),
                    capacity=ScaleCapacity(minimum=p.get('min_count'),
                                           maximum=p.get('max_count'),
                                           default=p.get('count')),
                    rules=[
                        create_rule_instance(r) for r in p.get('rules') or []
                    ],
                    fixed_date=TimeWindow(
                        time_zone=p.get('fixed_date_timezone'),
                        start=p.get('fixed_date_start'),
                        end=p.get('fixed_date_end'))
                    if p.get('fixed_date_timezone') else None,
                    recurrence=Recurrence(
                        frequency=p.get('recurrence_frequency'),
                        schedule=(RecurrentSchedule(
                            time_zone=p.get('recurrence_timezone'),
                            days=p.get('recurrence_days'),
                            hours=p.get('recurrence_hours'),
                            minutes=p.get('recurrence_mins'))))
                    if p.get('recurrence_frequency')
                    and p['recurrence_frequency'] != 'None' else None)
                for p in self.profiles or []
            ]

            notifications = [
                AutoscaleNotification(email=EmailNotification(**n),
                                      webhooks=[
                                          WebhookNotification(service_uri=w)
                                          for w in n.get('webhooks') or []
                                      ]) for n in self.notifications or []
            ]

            if not results:
                # create new
                changed = True
            else:
                # check changed
                resource_name = results.autoscale_setting_resource_name or self.name
                update_tags, tags = self.update_tags(results.tags)
                if update_tags:
                    changed = True
                    self.tags = tags
                if self.target != results.target_resource_uri:
                    changed = True
                if self.enabled != results.enabled:
                    changed = True
                profile_result_set = set(
                    [str(profile_to_dict(p)) for p in results.profiles or []])
                if profile_result_set != set(
                    [str(profile_to_dict(p)) for p in profiles]):
                    changed = True
                notification_result_set = set([
                    str(notification_to_dict(n))
                    for n in results.notifications or []
                ])
                if notification_result_set != set(
                    [str(notification_to_dict(n)) for n in notifications]):
                    changed = True
            if changed:
                # construct the instance will be send to create_or_update api
                results = AutoscaleSettingResource(
                    location=self.location,
                    tags=self.tags,
                    profiles=profiles,
                    notifications=notifications,
                    enabled=self.enabled,
                    autoscale_setting_resource_name=resource_name,
                    target_resource_uri=self.target)
                if not self.check_mode:
                    results = self.create_or_update_auto_scale(results)
                # results should be the dict of the instance
        self.results = auto_scale_to_dict(results)
        self.results['changed'] = changed
        return self.results
Beispiel #4
0
def create_auto_scale_profile(
    queue_uri: str,
    min: int,
    max: int,
    default: int,
    scale_out_amount: int,
    scale_out_cooldown: int,
    scale_in_amount: int,
    scale_in_cooldown: int,
) -> AutoscaleProfile:
    return AutoscaleProfile(
        name=str(uuid.uuid4()),
        capacity=ScaleCapacity(minimum=min, maximum=max, default=max),
        # Auto scale tuning guidance:
        # https://docs.microsoft.com/en-us/azure/architecture/best-practices/auto-scaling
        rules=[
            ScaleRule(
                metric_trigger=MetricTrigger(
                    metric_name="ApproximateMessageCount",
                    metric_resource_uri=queue_uri,
                    # Check every 15 minutes
                    time_grain=timedelta(minutes=15),
                    # The average amount of messages there are in the pool queue
                    time_aggregation=TimeAggregationType.AVERAGE,
                    statistic=MetricStatisticType.COUNT,
                    # Over the past 15 minutes
                    time_window=timedelta(minutes=15),
                    # When there's more than 1 message in the pool queue
                    operator=ComparisonOperationType.GREATER_THAN_OR_EQUAL,
                    threshold=1,
                    divide_per_instance=False,
                ),
                scale_action=ScaleAction(
                    direction=ScaleDirection.INCREASE,
                    type=ScaleType.CHANGE_COUNT,
                    value=scale_out_amount,
                    cooldown=timedelta(minutes=scale_out_cooldown),
                ),
            ),
            # Scale in
            ScaleRule(
                # Scale in if no work in the past 20 mins
                metric_trigger=MetricTrigger(
                    metric_name="ApproximateMessageCount",
                    metric_resource_uri=queue_uri,
                    # Check every 10 minutes
                    time_grain=timedelta(minutes=10),
                    # The average amount of messages there are in the pool queue
                    time_aggregation=TimeAggregationType.AVERAGE,
                    statistic=MetricStatisticType.SUM,
                    # Over the past 10 minutes
                    time_window=timedelta(minutes=10),
                    # When there's no messages in the pool queue
                    operator=ComparisonOperationType.EQUALS,
                    threshold=0,
                    divide_per_instance=False,
                ),
                scale_action=ScaleAction(
                    direction=ScaleDirection.DECREASE,
                    type=ScaleType.CHANGE_COUNT,
                    value=scale_in_amount,
                    cooldown=timedelta(minutes=scale_in_cooldown),
                ),
            ),
        ],
    )