def test__can_watch_fields(self): connect_to_field_change = self.patch_autospec( signals_module, "connect_to_field_change") connect_to_field_change.return_value = ( sentinel.connect, sentinel.disconnect, ) manager = SignalsManager() manager.watch_fields(sentinel.callback, sentinel.model, sentinel.fields, sentinel.delete) self.assertThat( manager._signals, Equals({Signal(sentinel.connect, sentinel.disconnect)}), ) self.assertThat( connect_to_field_change, MockCalledOnceWith( sentinel.callback, sentinel.model, sentinel.fields, sentinel.delete, ), )
"""Updates the `StaticIPAddress`'s to ensure that they are linked to the correct subnet.""" # Remove the IP addresses that no longer fall with in the CIDR. remove_ips = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet_id=subnet.id) remove_ips = remove_ips.extra(where=["NOT(ip << %s)"], params=[subnet.cidr]) remove_ips.update(subnet=None) # Add the IP addresses that now fall into CIDR. add_ips = StaticIPAddress.objects.filter(subnet__isnull=True) add_ips = add_ips.extra(where=["ip << %s"], params=[subnet.cidr]) add_ips.update(subnet_id=subnet.id) def post_created(sender, instance, created, **kwargs): if created: update_referenced_ip_addresses(instance) def updated_cidr(instance, old_values, **kwargs): update_referenced_ip_addresses(instance) signals.watch(post_save, post_created, sender=Subnet) signals.watch_fields(updated_cidr, Subnet, ["cidr"], delete=False) # Enable all signals by default. signals.enable()
alloc_type=IPADDRESS_TYPE.DISCOVERED ): instance.unlink_ip_address(ip_address, clearing_config=True) # If any of the children of this interface are now disabled, all of # their links need to be removed as well. for rel in instance.children_relationships.all(): if not rel.child.is_enabled(): for ip_address in rel.child.ip_addresses.all(): rel.child.unlink_ip_address( ip_address, clearing_config=True ) for klass in INTERFACE_CLASSES: signals.watch_fields( interface_enabled_or_disabled, klass, ["enabled"], delete=False ) def _update_mtu(interface, mtu, instance): log.msg( "%s: MTU updated to %d (for consistency with %s)." % (interface.get_log_string(), mtu, instance.get_log_string()) ) params = interface.params.copy() params["mtu"] = mtu interface.params = params interface.save() def interface_mtu_params_update(instance, old_values, **kwargs):
This schedules a check of the node's power state after a delay of `WAIT_TO_QUERY`. :return: A `DelayedCall` instance, describing the pending update. Don't use this outside of the reactor thread though! """ return clock.callLater( WAIT_TO_QUERY.total_seconds(), update_power_state_of_node, system_id ) @synchronous def signal_update_power_state_of_node(instance, old_values, **kwargs): """Updates the power state of a node, when its status changes.""" node = instance [old_status] = old_values # Only check the power state if it's an interesting transition. if old_status in QUERY_TRANSITIONS: if node.status in QUERY_TRANSITIONS[old_status]: post_commit().addCallback( callOut, update_power_state_of_node_soon, node.system_id ) signals.watch_fields(signal_update_power_state_of_node, Node, ["status"]) # Enable all signals by default. signals.enable()
return node = instance [old_status] = old_values type_name = EVENT_TYPES.NODE_CHANGED_STATUS event_details = EVENT_DETAILS[type_name] description = "From '%s' to '%s'" % ( NODE_STATUS_CHOICES_DICT[old_status], NODE_STATUS_CHOICES_DICT[node.status], ) # Special-case for allocating nodes: we can include usernames here # to make the event log more useful. if node.status == NODE_STATUS.ALLOCATED: description += " (to %s)" % node.owner.username Event.objects.register_event_and_event_type( type_name, type_level=event_details.level, type_description=event_details.description, event_description=description, system_id=node.system_id) signals.watch_fields(emit_state_transition_event, Node, ['status'], delete=False) # Enable all signals by default. signals.enable()
) else: old_status_name = None new_status_name = None for status, status_name in SCRIPT_STATUS_CHOICES: if old_status == status: old_status_name = status_name elif script_result.status == status: new_status_name = status_name Event.objects.create_node_event( script_result.script_set.node, EVENT_TYPES.SCRIPT_RESULT_CHANGED_STATUS, event_description="%s changed status from '%s' to '%s'" % (script_name, old_status_name, new_status_name), ) if (CURTIN_INSTALL_LOG == script_result.name and not script_result.script_set.node.netboot): Event.objects.create_node_event(script_result.script_set.node, EVENT_TYPES.REBOOTING) signals.watch_fields( emit_script_result_status_transition_event, ScriptResult, ["status"], delete=False, ) # Enable all signals by default. signals.enable()
# Was disabled. Remove the links. for ip_address in instance.ip_addresses.exclude( alloc_type=IPADDRESS_TYPE.DISCOVERED): instance.unlink_ip_address(ip_address, clearing_config=True) # If any of the children of this interface are now disabled, all of # their links need to be removed as well. for rel in instance.children_relationships.all(): if not rel.child.is_enabled(): for ip_address in rel.child.ip_addresses.all(): rel.child.unlink_ip_address( ip_address, clearing_config=True) for klass in INTERFACE_CLASSES: signals.watch_fields( interface_enabled_or_disabled, klass, ['enabled'], delete=False) def _update_mtu(interface, mtu, instance): log.msg("%s: MTU updated to %d (for consistency with %s)." % ( interface.get_log_string(), mtu, instance.get_log_string())) params = interface.params.copy() params['mtu'] = mtu interface.params = params interface.save() def interface_mtu_params_update(instance, old_values, **kwargs): """When an interfaces MTU is changed we need to do two things.
type_name = EVENT_TYPES.NODE_CHANGED_STATUS event_details = EVENT_DETAILS[type_name] description = "From '%s' to '%s'" % ( NODE_STATUS_CHOICES_DICT[old_status], NODE_STATUS_CHOICES_DICT[node.status], ) # Special-case for allocating nodes: we can include usernames here # to make the event log more useful. if node.status == NODE_STATUS.ALLOCATED: description += " (to %s)" % node.owner.username Event.objects.register_event_and_event_type( type_name, type_level=event_details.level, type_description=event_details.description, event_description=description, system_id=node.system_id, ) for klass in NODE_CLASSES: # Watch the status of all classes, as the node might switch types. # Only if its a machine will the handler care. signals.watch_fields(emit_state_transition_event, klass, ["status"], delete=False) # Enable all signals by default. signals.enable()
def clear_nodekey_when_owner_changes(node, old_values, deleted=False): """Erase related `NodeKey` when node ownership changes.""" assert not deleted, ("clear_nodekey_when_owner_changes is not prepared " "to deal with deletion of nodes.") owner_id_old = old_values[0] owner_id_new = node.owner_id if owner_id_new != owner_id_old: NodeKey.objects.clear_token_for_node(node) for klass in NODE_CLASSES: signals.watch_fields(clear_nodekey_when_owner_changes, klass, ['owner_id'], delete=False) def create_services_on_node_type_change(node, old_values, deleted=False): """Create services when node_type changes.""" old_node_type = old_values[0] new_node_type = node.node_type if new_node_type != old_node_type: Service.objects.create_services_for(node) def create_services_on_create(sender, instance, created, **kwargs): """Create services when node created.""" if created: Service.objects.create_services_for(instance)