Esempio n. 1
0
def autoscale_rule_create(cmd, client, autoscale_name, resource_group_name, condition,
                          scale, profile_name=DEFAULT_PROFILE_NAME, cooldown=5, source=None,
                          timegrain="avg 1m"):
    from azure.mgmt.monitor.models import ScaleRule, ScaleAction, ScaleDirection
    autoscale_settings = client.get(resource_group_name, autoscale_name)
    profile = next(x for x in autoscale_settings.profiles if x.name == profile_name)
    condition.metric_resource_uri = source or autoscale_settings.target_resource_uri
    condition.statistic = timegrain.statistic
    condition.time_grain = timegrain.time_grain
    rule = ScaleRule(
        metric_trigger=condition,
        scale_action=ScaleAction(
            direction=scale.direction,
            type=scale.type,
            cooldown='PT{}M'.format(cooldown),
            value=scale.value)
    )
    profile.rules.append(rule)
    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)

    # determine if there are unbalanced rules
    scale_out_rule_count = len([x for x in profile.rules if x.scale_action.direction == ScaleDirection.increase])
    scale_in_rule_count = len([x for x in profile.rules if x.scale_action.direction == ScaleDirection.decrease])
    if scale_out_rule_count and not scale_in_rule_count:
        logger.warning("Profile '%s' has rules to scale out but none to scale in. "
                       "Recommend creating at least 1 scale in rule.", profile_name)
    elif scale_in_rule_count and not scale_out_rule_count:
        logger.warning("Profile '%s' has rules to scale in but none to scale out. "
                       "Recommend creating at least 1 scale out rule.", profile_name)
    return rule
 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))
def create_autoscaling_settings(ExistingVmScaleSetName, VmScaleSetID,
                                resourceGroupName):
    NewVmScaleSetName = VmScaleSetID.split('/')[-1]
    existing_asg = monitor_client.autoscale_settings.get(
        resource_group_name=resourceGroupName,
        autoscale_setting_name=ExistingVmScaleSetName)
    rules = [
        ScaleRule(
            metric_trigger=MetricTrigger(
                metric_name=i.metric_trigger.metric_name,
                #metric_namespace=i.metric_trigger.additional_properties['metricNamespace'],
                metric_resource_uri=VmScaleSetID,
                time_grain=i.metric_trigger.time_grain,
                statistic=i.metric_trigger.statistic,
                time_window=i.metric_trigger.time_window,
                time_aggregation=i.metric_trigger.time_aggregation,
                operator=i.metric_trigger.operator,
                threshold=i.metric_trigger.threshold
                #dimensions = i.metric_trigger.additional_properties['dimensions']
            ),
            scale_action=i.scale_action)
        for i in existing_asg.profiles[0].rules
    ]
    profile = AutoscaleProfile(name=existing_asg.profiles[0].name,
                               capacity=existing_asg.profiles[0].capacity,
                               rules=rules,
                               fixed_date=None,
                               recurrence=None)
    parameters = AutoscaleSettingResource(
        location=existing_asg.location,
        tags=existing_asg.tags,
        profiles=[profile],
        notifications=existing_asg.notifications,
        enabled=True,
        autoscale_setting_resource_name=NewVmScaleSetName,
        target_resource_uri=VmScaleSetID)
    new_asg = monitor_client.autoscale_settings.create_or_update(
        resource_group_name=resourceGroupName,
        autoscale_setting_name=NewVmScaleSetName,
        parameters=parameters)
Esempio n. 4
0
def shutdown_scaleset_rule(queue_uri: str) -> ScaleRule:
    return ScaleRule(
        # Scale in if there are 0 or more messages in the queue (aka: every time)
        metric_trigger=MetricTrigger(
            metric_name="ApproximateMessageCount",
            metric_resource_uri=queue_uri,
            # Check every 10 minutes
            time_grain=timedelta(minutes=5),
            # 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=5),
            operator=ComparisonOperationType.GREATER_THAN_OR_EQUAL,
            threshold=0,
            divide_per_instance=False,
        ),
        scale_action=ScaleAction(
            direction=ScaleDirection.DECREASE,
            type=ScaleType.CHANGE_COUNT,
            value=1,
            cooldown=timedelta(minutes=5),
        ),
    )
Esempio n. 5
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),
                ),
            ),
        ],
    )
Esempio n. 6
0
def autoscale_rule_create(cmd,
                          client,
                          autoscale_name,
                          resource_group_name,
                          condition,
                          scale,
                          profile_name=DEFAULT_PROFILE_NAME,
                          cooldown=5,
                          source=None,
                          timegrain="avg 1m"):
    from azure.mgmt.monitor.models import ScaleRule, ScaleAction, ScaleDirection
    from azure.mgmt.core.tools import parse_resource_id, resource_id
    autoscale_settings = client.get(resource_group_name, autoscale_name)
    profile = _identify_profile(autoscale_settings.profiles, profile_name)
    condition.metric_resource_uri = source or autoscale_settings.target_resource_uri
    condition.statistic = timegrain.statistic
    condition.time_grain = timegrain.time_grain

    def preprocess_for_spring_cloud_service():
        try:
            result = parse_resource_id(autoscale_settings.target_resource_uri)
            if result['namespace'].lower(
            ) == 'microsoft.appplatform' and result['type'].lower(
            ) == 'spring':
                if condition.metric_namespace is None:
                    condition.metric_namespace = "Microsoft.AppPlatform/Spring"
                    logger.warning(
                        'Set metricNamespace to Microsoft.AppPlatform/Spring')
                if source is None:
                    condition.metric_resource_uri = resource_id(
                        subscription=result['subscription'],
                        resource_group=result['resource_group'],
                        namespace=result['namespace'],
                        type=result['type'],
                        name=result['name'])
                    logger.warning(
                        'Set metricResourceUri to Spring Cloud service')
        except KeyError:
            pass

    preprocess_for_spring_cloud_service()

    rule = ScaleRule(metric_trigger=condition,
                     scale_action=ScaleAction(
                         direction=scale.direction,
                         type=scale.type,
                         cooldown='PT{}M'.format(cooldown),
                         value=scale.value))
    profile.rules.append(rule)
    autoscale_settings = client.create_or_update(resource_group_name,
                                                 autoscale_name,
                                                 autoscale_settings)

    # determine if there are unbalanced rules
    scale_out_rule_count = len([
        x for x in profile.rules
        if x.scale_action.direction == ScaleDirection.increase
    ])
    scale_in_rule_count = len([
        x for x in profile.rules
        if x.scale_action.direction == ScaleDirection.decrease
    ])
    if scale_out_rule_count and not scale_in_rule_count:
        logger.warning(
            "Profile '%s' has rules to scale out but none to scale in. "
            "Recommend creating at least 1 scale in rule.", profile_name)
    elif scale_in_rule_count and not scale_out_rule_count:
        logger.warning(
            "Profile '%s' has rules to scale in but none to scale out. "
            "Recommend creating at least 1 scale out rule.", profile_name)
    return rule