def converge_scaling_group(self, request): """ Trigger convergence on given scaling group """ class ConvergeErrorGroup(Exception): pass def can_converge(group, state): if state.paused: raise GroupPausedError(group.tenant_id, group.uuid, "converge") conv_on_error = extract_bool_arg(request, 'on_error', True) if not conv_on_error and state.status == ScalingGroupStatus.ERROR: raise ConvergeErrorGroup() return state def converge_error_group_header(f): f.trap(ConvergeErrorGroup) request.setHeader("x-not-converging", "true") if tenant_is_enabled(self.tenant_id, config_value): group = self.store.get_scaling_group( self.log, self.tenant_id, self.group_id) return controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(self.log), can_converge).addErrback(converge_error_group_header) else: request.setResponseCode(404)
def match(self, log): """ Return None if log is bound with given args/kwargs. Otherwise return Mismatch """ if not isinstance(log, BoundLog): return Mismatch('log is not a BoundLog') kwargs = bound_log_kwargs(log) if self.kwargs == kwargs: return None else: return Mismatch('Expected kwargs {} but got {} instead'.format( self.kwargs, kwargs))
def match(self, log): """ Return None if log is bound with given args/kwargs. Otherwise return Mismatch """ if not isinstance(log, BoundLog): return Mismatch('log is not a BoundLog') kwargs = bound_log_kwargs(log) if self.kwargs == kwargs: return None else: return Mismatch( 'Expected kwargs {} but got {} instead'.format(self.kwargs, kwargs))
def execute_policy((tenant_id, group_id, policy_id)): bound_log = self.log.bind(tenant_id=tenant_id, scaling_group_id=group_id, policy_id=policy_id) logl[0] = bound_log group = self.store.get_scaling_group(bound_log, tenant_id, group_id) return controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(bound_log), partial(controller.maybe_execute_scaling_policy, bound_log, transaction_id(request), policy_id=policy_id), modify_state_reason='execute_webhook')
def _do_obey_config_change(result): group_id = result['id'] config = result['groupConfiguration'] launch = result['launchConfiguration'] group = self.store.get_scaling_group( self.log, self.tenant_id, group_id) log = self.log.bind(scaling_group_id=group_id) d = controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(log), partial( controller.obey_config_change, log, transaction_id(request), config, launch_config=launch), modify_state_reason='create_new_scaling_group') return d.addCallback(lambda _: result)
def edit_config_for_scaling_group(self, request, data): """ Edit the configuration for a scaling group, which includes the minimum number of entities, the maximum number of entities, global cooldown, and other metadata. This data provided in the request body in JSON format. If successful, no response body will be returned. Example request:: { "name": "workers", "cooldown": 60, "minEntities": 5, "maxEntities": 100, "metadata": { "firstkey": "this is a string", "secondkey": "1", } } The entire schema body must be provided. """ if data['minEntities'] > data['maxEntities']: raise InvalidMinEntities( "minEntities must be less than or equal to maxEntities") def _get_launch_and_obey_config_change(scaling_group, state): d = scaling_group.view_launch_config() d.addCallback(partial( controller.obey_config_change, self.log, transaction_id(request), data, scaling_group, state)) return d group = self.store.get_scaling_group( self.log, self.tenant_id, self.group_id) deferred = group.update_config(data) deferred.addCallback( lambda _: controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(log), _get_launch_and_obey_config_change, modify_state_reason='edit_config_for_scaling_group')) return deferred
def delete_server(self, request, server_id): """ Delete a server from the group. """ group = self.store.get_scaling_group(self.log, self.tenant_id, self.scaling_group_id) log = self.log.bind(server_id=server_id) d = controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(log), partial(controller.remove_server_from_group, self.dispatcher, log, transaction_id(request), server_id, extract_bool_arg(request, 'replace', True), extract_bool_arg(request, 'purge', True)), modify_state_reason='delete_server') return d
def converge_scaling_group(self, request): """ Trigger convergence on given scaling group """ def can_converge(group, state): if state.paused: raise GroupPausedError(group.tenant_id, group.uuid, "converge") return state if tenant_is_enabled(self.tenant_id, config_value): group = self.store.get_scaling_group(self.log, self.tenant_id, self.group_id) return controller.modify_and_trigger(self.dispatcher, group, bound_log_kwargs(self.log), can_converge) else: request.setResponseCode(404)
def execute_event(dispatcher, store, log, event, deleted_policy_ids): """ Execute a single event :param dispatcher: Effect dispatcher :param store: `IScalingGroupCollection` provider :param log: A bound log for logging :param event: event dict to execute :param deleted_policy_ids: Set of policy ids that are deleted. Policy id will be added to this if its scaling group or policy has been deleted :return: a deferred with None. Any error occurred during execution is logged """ tenant_id = event['tenantId'] group_id = event['groupId'] policy_id = event['policyId'] log = log.bind(tenant_id=tenant_id, scaling_group_id=group_id, policy_id=policy_id, scheduled_time=event["trigger"].isoformat() + "Z") log.msg('sch-exec-pol', cloud_feed=True) group = store.get_scaling_group(log, tenant_id, group_id) d = modify_and_trigger(dispatcher, group, bound_log_kwargs(log), partial(maybe_execute_scaling_policy, log, generate_transaction_id(), policy_id=policy_id, version=event['version']), modify_state_reason='scheduler.execute_event') d.addErrback(ignore_and_log, CannotExecutePolicyError, log, "sch-cannot-exec", cloud_feed=True) def collect_deleted_policy(failure): failure.trap(NoSuchScalingGroupError, NoSuchPolicyError) deleted_policy_ids.add(policy_id) d.addErrback(collect_deleted_policy) d.addErrback(log.err, "sch-exec-pol-err", cloud_feed=True) return d
def delete_server(self, request, server_id): """ Delete a server from the group. """ group = self.store.get_scaling_group( self.log, self.tenant_id, self.scaling_group_id) log = self.log.bind(server_id=server_id) d = controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(log), partial(controller.remove_server_from_group, self.dispatcher, log, transaction_id(request), server_id, extract_bool_arg(request, 'replace', True), extract_bool_arg(request, 'purge', True)), modify_state_reason='delete_server') return d
def execute_event(dispatcher, store, log, event, deleted_policy_ids): """ Execute a single event :param dispatcher: Effect dispatcher :param store: `IScalingGroupCollection` provider :param log: A bound log for logging :param event: event dict to execute :param deleted_policy_ids: Set of policy ids that are deleted. Policy id will be added to this if its scaling group or policy has been deleted :return: a deferred with None. Any error occurred during execution is logged """ tenant_id = event["tenantId"] group_id = event["groupId"] policy_id = event["policyId"] log = log.bind( tenant_id=tenant_id, scaling_group_id=group_id, policy_id=policy_id, scheduled_time=event["trigger"].isoformat() + "Z", ) log.msg("sch-exec-pol", cloud_feed=True) group = store.get_scaling_group(log, tenant_id, group_id) d = modify_and_trigger( dispatcher, group, bound_log_kwargs(log), partial( maybe_execute_scaling_policy, log, generate_transaction_id(), policy_id=policy_id, version=event["version"] ), modify_state_reason="scheduler.execute_event", ) d.addErrback(ignore_and_log, CannotExecutePolicyError, log, "sch-cannot-exec", cloud_feed=True) def collect_deleted_policy(failure): failure.trap(NoSuchScalingGroupError, NoSuchPolicyError) deleted_policy_ids.add(policy_id) d.addErrback(collect_deleted_policy) d.addErrback(log.err, "sch-exec-pol-err", cloud_feed=True) return d
def converge_scaling_group(self, request): """ Trigger convergence on given scaling group """ def is_group_paused(group, state): if state.paused: raise GroupPausedError(group.tenant_id, group.uuid, "converge") return state if tenant_is_enabled(self.tenant_id, config_value): group = self.store.get_scaling_group( self.log, self.tenant_id, self.group_id) return controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(log), is_group_paused) else: request.setResponseCode(404)
def execute_policy(self, request): """ Execute this scaling policy. TBD: Response body. Example response:: {} """ group = self.store.get_scaling_group(self.log, self.tenant_id, self.scaling_group_id) d = controller.modify_and_trigger( self.dispatcher, group, bound_log_kwargs(self.log), partial(controller.maybe_execute_scaling_policy, self.log, transaction_id(request), policy_id=self.policy_id), modify_state_reason='execute_policy') d.addCallback(lambda _: "{}") # Return value TBD return d