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
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)
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
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), ), ), ], )