/** Enterprise Control Configuration and Logging Copyright (C) 2012 Free Software Foundation, Inc. Written by: Richard Frith-Macdonald Date: Febrary 2010 Originally developed from 1996 to 2012 by Brainstorm, and donated to the FSF. This file is part of the GNUstep project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #import #import #import #import #import #import #import #import "EcHost.h" #import "EcProcess.h" #import "EcAlarm.h" @class NSPortCoder; NSString * EcMakeManagedObject(NSString *host, NSString *process, NSString *component) { NSString *instance = @""; NSRange r; if (nil == host) { host = [[NSHost currentHost] wellKnownName]; } // No underscores permitted. host = [host stringByTrimmingSpaces]; host = [host stringByReplacingString: @"_" withString: @"-"]; if (nil == process) { process = [EcProc cmdName]; } /* Extract the instance number from the process name (the instance would * be a string of digits after a hyphen) if it's there. */ r = [process rangeOfString: @"-" options: NSCaseInsensitiveSearch|NSBackwardsSearch]; if (r.length > 0) { NSString *s = [process substringFromIndex: NSMaxRange(r)]; unsigned l = [s length]; if (l > 0) { while (l-- > 0) { unichar c = [s characterAtIndex: l]; if (c < '0' || c > '9') { break; } } if (0 == l) { instance = s; process = [process substringToIndex: r.location]; } } } // No underscores permitted. process = [process stringByTrimmingSpaces]; process = [process stringByReplacingString: @"_" withString: @"-"]; if (nil == component) { component = @""; } // No underscores permitted. component = [component stringByTrimmingSpaces]; component = [component stringByReplacingString: @"_" withString: @"-"]; return [NSString stringWithFormat: @"%@_%@_%@_%@", host, process, instance, component]; } @implementation EcAlarm + (void) initialize { if (self == [EcAlarm class]) { [self setVersion: 2]; } } + (EcAlarm*) alarmForManagedObject: (NSString*)managedObject at: (NSDate*)eventDate withEventType: (EcAlarmEventType)eventType probableCause: (EcAlarmProbableCause)probableCause specificProblem: (NSString*)specificProblem perceivedSeverity: (EcAlarmSeverity)perceivedSeverity proposedRepairAction: (NSString*)proposedRepairAction additionalText: (NSString*)additionalText { EcAlarm *a = [self alloc]; a = [a initForManagedObject: managedObject at: eventDate withEventType: eventType probableCause: probableCause specificProblem: specificProblem perceivedSeverity: perceivedSeverity proposedRepairAction: proposedRepairAction additionalText: additionalText]; return [a autorelease]; } + (EcAlarmEventType) eventTypeFromProbableCause: (EcAlarmProbableCause)value { switch (value) { case EcAlarmProbableCauseUnknown: // Don't call with this value return EcAlarmEventTypeUnknown; case EcAlarmCallEstablishmentError: case EcAlarmCommunicationsProtocolError: case EcAlarmCommunicationsSubsystemFailure: case EcAlarmDegradedSignal: case EcAlarmDTE_DCEInterfaceError: case EcAlarmFramingError: case EcAlarmLANError: case EcAlarmLocalNodeTransmissionError: case EcAlarmLossOfFrame: case EcAlarmLossOfSignal: case EcAlarmRemoteNodeTransmissionError: return EcAlarmEventTypeCommunications; case EcAlarmEnclosureDoorOpen: case EcAlarmExcessiveVibration: case EcAlarmFireDetected: case EcAlarmFloodDetected: case EcAlarmHeatingOrVentilationOrCoolingSystemProblem: case EcAlarmHumidityUnacceptable: case EcAlarmLeakDetected: case EcAlarmMaterialSupplyExhausted: case EcAlarmPressureUnacceptable: case EcAlarmPumpFailure: case EcAlarmTemperatureUnacceptable: case EcAlarmToxicLeakDetected: return EcAlarmEventTypeEnvironmental; case EcAlarmAdapterError: case EcAlarmDataSetOrModemError: case EcAlarmEquipmentMalfunction: case EcAlarmInputDeviceError: case EcAlarmInputOutputDeviceError: case EcAlarmMultiplexerProblem: case EcAlarmOutputDeviceError: case EcAlarmPowerProblem: case EcAlarmProcessorProblem: case EcAlarmReceiveFailure: case EcAlarmReceiverFailure: case EcAlarmTimingProblem: case EcAlarmTransmitFailure: case EcAlarmTransmitterFailure: return EcAlarmEventTypeEquipment; case EcAlarmApplicationSubsystemFailure: case EcAlarmConfigurationOrCustomizationError: case EcAlarmCorruptData: case EcAlarmCpuCyclesLimitExceeded: case EcAlarmFileError: case EcAlarmOutOfMemory: case EcAlarmSoftwareProgramAbnormallyTerminated: case EcAlarmSoftwareProgramError: case EcAlarmStorageCapacityProblem: case EcAlarmUnderlyingResourceUnavailable: case EcAlarmVersionMismatch: return EcAlarmEventTypeProcessingError; case EcAlarmBandwidthReduced: case EcAlarmCongestion: case EcAlarmPerformanceDegraded: case EcAlarmQueueSizeExceeded: case EcAlarmResourceAtOrNearingCapacity: case EcAlarmResponseTimeExcessive: case EcAlarmRetransmissionRateExcessive: case EcAlarmThresholdCrossed: return EcAlarmEventTypeQualityOfService; } return EcAlarmEventTypeUnknown; } + (NSString*) stringFromEventType: (EcAlarmEventType)value { switch (value) { case EcAlarmEventTypeUnknown: // Not legal return nil; case EcAlarmEventTypeCommunications: return @"communications"; case EcAlarmEventTypeEnvironmental: return @"environmental"; case EcAlarmEventTypeEquipment: return @"equipment"; case EcAlarmEventTypeProcessingError: return @"processingError"; case EcAlarmEventTypeQualityOfService: return @"qualityOfService"; } return nil; } + (NSString*) stringFromProbableCause: (EcAlarmProbableCause)value { switch (value) { case EcAlarmProbableCauseUnknown: return @"ProbableCauseUnknown"; case EcAlarmAdapterError: return @"adapterError"; case EcAlarmApplicationSubsystemFailure: return @"applicationSubsystemFailure"; case EcAlarmBandwidthReduced: return @"bandwidthReduced"; case EcAlarmCallEstablishmentError: return @"callEstablishmentError"; case EcAlarmCommunicationsProtocolError: return @"communicationsProtocolError"; case EcAlarmCommunicationsSubsystemFailure: return @"communicationsSubsystemFailure"; case EcAlarmConfigurationOrCustomizationError: return @"configurationOrCustomizationError"; case EcAlarmCongestion: return @"congestion"; case EcAlarmCorruptData: return @"corruptData"; case EcAlarmCpuCyclesLimitExceeded: return @"cpuCyclesLimitExceeded"; case EcAlarmDataSetOrModemError: return @"dataSetOrModemError"; case EcAlarmDegradedSignal: return @"degradedSignal"; case EcAlarmDTE_DCEInterfaceError: return @"dTE-DCEInterfaceError"; case EcAlarmEnclosureDoorOpen: return @"enclosureDoorOpen"; case EcAlarmEquipmentMalfunction: return @"equipmentMalfunction"; case EcAlarmExcessiveVibration: return @"excessiveVibration"; case EcAlarmFileError: return @"fileError"; case EcAlarmFireDetected: return @"fireDetected"; case EcAlarmFloodDetected: return @"floodDetected"; case EcAlarmFramingError: return @"framingError"; case EcAlarmHeatingOrVentilationOrCoolingSystemProblem: return @"heatingOrVentilationOrCoolingSystemProblem"; case EcAlarmHumidityUnacceptable: return @"humidityUnacceptable"; case EcAlarmInputOutputDeviceError: return @"inputOutputDeviceError"; case EcAlarmInputDeviceError: return @"inputDeviceError"; case EcAlarmLANError: return @"lANError"; case EcAlarmLeakDetected: return @"leakDetected"; case EcAlarmLocalNodeTransmissionError: return @"localNodeTransmissionError"; case EcAlarmLossOfFrame: return @"lossOfFrame"; case EcAlarmLossOfSignal: return @"lossOfSignal"; case EcAlarmMaterialSupplyExhausted: return @"materialSupplyExhausted"; case EcAlarmMultiplexerProblem: return @"multiplexerProblem"; case EcAlarmOutOfMemory: return @"outOfMemory"; case EcAlarmOutputDeviceError: return @"outputDeviceError"; case EcAlarmPerformanceDegraded: return @"performanceDegraded"; case EcAlarmPowerProblem: return @"powerProblem"; case EcAlarmPressureUnacceptable: return @"pressureUnacceptable"; case EcAlarmProcessorProblem: return @"processorProblem"; case EcAlarmPumpFailure: return @"pumpFailure"; case EcAlarmQueueSizeExceeded: return @"queueSizeExceeded"; case EcAlarmReceiveFailure: return @"receiveFailure"; case EcAlarmReceiverFailure: return @"receiverFailure"; case EcAlarmRemoteNodeTransmissionError: return @"remoteNodeTransmissionError"; case EcAlarmResourceAtOrNearingCapacity: return @"resourceAtOrNearingCapacity"; case EcAlarmResponseTimeExcessive: return @"responseTimeExcessive"; case EcAlarmRetransmissionRateExcessive: return @"retransmissionRateExcessive"; case EcAlarmSoftwareProgramAbnormallyTerminated: return @"softwareProgramAbnormallyTerminated"; case EcAlarmSoftwareProgramError: return @"softwareProgramError"; case EcAlarmStorageCapacityProblem: return @"storageCapacityProblem"; case EcAlarmTemperatureUnacceptable: return @"temperatureUnacceptable"; case EcAlarmThresholdCrossed: return @"thresholdCrossed"; case EcAlarmTimingProblem: return @"timingProblem"; case EcAlarmToxicLeakDetected: return @"toxicLeakDetected"; case EcAlarmTransmitFailure: return @"transmitFailure"; case EcAlarmTransmitterFailure: return @"transmitterFailure"; case EcAlarmUnderlyingResourceUnavailable: return @"underlyingResourceUnavailable"; case EcAlarmVersionMismatch: return @"versionMismatch"; } return nil; } + (NSString*) stringFromSeverity: (EcAlarmSeverity)value { switch (value) { case EcAlarmSeverityIndeterminate: return @"indeterminate"; case EcAlarmSeverityCritical: return @"critical"; case EcAlarmSeverityMajor: return @"major"; case EcAlarmSeverityMinor: return @"minor"; case EcAlarmSeverityWarning: return @"warning"; case EcAlarmSeverityCleared: return @"cleared"; } return nil; } + (NSString*) stringFromTrend: (EcAlarmTrend)value { switch (value) { case EcAlarmTrendNone: return @"none"; case EcAlarmTrendUp: return @"up"; case EcAlarmTrendDown: return @"down"; } return nil; } - (NSString*) additionalText { return _additionalText; } - (Class) classForCoder { return [EcAlarm class]; } - (EcAlarm*) clear { EcAlarm *c = [self copy]; c->_perceivedSeverity = EcAlarmSeverityCleared; c->_notificationID = _notificationID; return [c autorelease]; } - (NSComparisonResult) compare: (EcAlarm*)other { int oNotificationID; NSString *sStr; NSString *oStr; if (NO == [other isKindOfClass: [EcAlarm class]]) { [NSException raise: NSInvalidArgumentException format: @"[%@-%@] argument is not an EcAlarm", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } oNotificationID = [other notificationID]; if (_notificationID > 0 && oNotificationID > 0) { if (_notificationID < oNotificationID) { return NSOrderedAscending; } if (_notificationID > oNotificationID) { return NSOrderedDescending; } return NSOrderedSame; } sStr = [NSString stringWithFormat: @"%@ %d %d %@", [self managedObject], [self eventType], [self probableCause], [self specificProblem]]; oStr = [NSString stringWithFormat: @"%@ %d %d %@", [other managedObject], [other eventType], [other probableCause], [other specificProblem]]; return [sStr compare: oStr]; } - (id) copyWithZone: (NSZone*)aZone { EcAlarm *c = [[self class] allocWithZone: aZone]; c = [c initForManagedObject: _managedObject at: _eventDate withEventType: _eventType probableCause: _probableCause specificProblem: _specificProblem perceivedSeverity: _perceivedSeverity proposedRepairAction: _proposedRepairAction additionalText: _additionalText]; if (nil != c) { c->_firstEventDate = [_firstEventDate copyWithZone: aZone]; c->_notificationID = _notificationID; c->_trendIndicator = _trendIndicator; c->_delay = _delay; ASSIGNCOPY(c->_userInfo, _userInfo); } return c; } - (void) dealloc { DESTROY(_userInfo); DESTROY(_managedObject); DESTROY(_eventDate); DESTROY(_firstEventDate); DESTROY(_specificProblem); DESTROY(_proposedRepairAction); DESTROY(_additionalText); [super dealloc]; } - (uint8_t) delay { return _delay; } - (BOOL) delayed: (NSTimeInterval)at { if (_delay > 0) { if (at < [_eventDate timeIntervalSinceReferenceDate] + _delay) { return YES; } } return NO; } - (NSString*) description { NSMutableString *s = [NSMutableString stringWithCapacity: 1000]; Class c = [self class]; if (0 == _notificationID) { [s appendString: _(@"Alarm address")]; [s appendFormat: @": 0x%"PRIxPTR", ", (uintptr_t)self]; } else { [s appendString: _(@"Alarm notification ID")]; [s appendFormat: @": %d, ", _notificationID]; } [s appendString: _(@"Managed object")]; [s appendFormat: @": %@, ", _managedObject]; [s appendString: _(@"Type")]; [s appendFormat: @": %@, ", [c stringFromEventType: _eventType]]; [s appendString: _(@"Cause")]; [s appendFormat: @": %@, ", [c stringFromProbableCause: _probableCause]]; [s appendString: _(@"Severity")]; [s appendFormat: @": %@, ", [c stringFromSeverity: _perceivedSeverity]]; [s appendString: _(@"Timestamp")]; [s appendFormat: @": %@, ", _eventDate]; if (EcAlarmTrendNone !=_trendIndicator) { [s appendString: _(@"Trend")]; [s appendFormat: @": %@", [c stringFromTrend: _trendIndicator]]; if (nil != _firstEventDate && NO == [_firstEventDate isEqual: _eventDate]) { [s appendString: @" "]; [s appendString: _(@"since")]; [s appendString: @" "]; [s appendString: [_firstEventDate description]]; } [s appendString: @", "]; } [s appendString: _(@"Problem")]; [s appendString: @": "]; [s appendString: _specificProblem]; if ([_additionalText length] > 0) { [s appendString: @": "]; [s appendString: _additionalText]; } [s appendString: @", "]; [s appendString: _(@"Proposed repair action")]; [s appendString: @": "]; [s appendString: _proposedRepairAction]; return s; } - (void) encodeWithCoder: (NSCoder*)aCoder { [aCoder encodeValuesOfObjCTypes: "iiiii@@@@@@@", &_eventType, &_notificationID, &_perceivedSeverity, &_probableCause, &_trendIndicator, &_managedObject, &_eventDate, &_firstEventDate, &_specificProblem, &_proposedRepairAction, &_additionalText, &_userInfo]; } - (NSDate*) eventDate { return _eventDate; } - (EcAlarmEventType) eventType { return _eventType; } - (void *) extra { return _extra; } - (NSDate*) firstEventDate { return _firstEventDate; } - (void) freeze { /* NB this value must NOT be archived ... because when we restore from * archive we will want to store a pointer in _extra. */ _frozen = YES; } - (NSUInteger) hash { return [_managedObject hash]; } - (id) init { [self release]; [NSException raise: NSInvalidArgumentException format: @"Called -init on EcAlarm"]; return nil; } - (id) initForManagedObject: (NSString*)managedObject at: (NSDate*)eventDate withEventType: (EcAlarmEventType)eventType probableCause: (EcAlarmProbableCause)probableCause specificProblem: (NSString*)specificProblem perceivedSeverity: (EcAlarmSeverity)perceivedSeverity proposedRepairAction: (NSString*)proposedRepairAction additionalText: (NSString*)additionalText { Class c = [self class]; if (nil == managedObject) { managedObject = EcMakeManagedObject(nil, nil, nil); } if (4 != [[managedObject componentsSeparatedByString: @"_"] count]) { [self release]; [NSException raise: NSInvalidArgumentException format: @"bad managed object (%@)", managedObject]; } if (127 < strlen([managedObject UTF8String])) { [self release]; [NSException raise: NSInvalidArgumentException format: @"managed object too long (over 127 bytes): (%@)", managedObject]; } if (0 == [specificProblem length]) { [self release]; [NSException raise: NSInvalidArgumentException format: @"empty specific problem"]; } if (255 < strlen([specificProblem UTF8String])) { [self release]; [NSException raise: NSInvalidArgumentException format: @"specific problem too long (over 255 bytes): (%@)", specificProblem]; } if (0 == [proposedRepairAction length]) { if (EcAlarmSeverityCleared == perceivedSeverity) { /* We don't need a proposed repair action for a clear. */ proposedRepairAction = @""; } else { [self release]; [NSException raise: NSInvalidArgumentException format: @"empty proposed repair action"]; } } if (255 < strlen([proposedRepairAction UTF8String])) { [self release]; [NSException raise: NSInvalidArgumentException format: @"proposed repair action too long (over 255 bytes): (%@)", proposedRepairAction]; } if (nil == eventDate) { eventDate = [NSDate date]; } if (nil == additionalText) { additionalText = @""; } if (255 < strlen([additionalText UTF8String])) { [self release]; [NSException raise: NSInvalidArgumentException format: @"additional text too long (over 255 bytes): (%@)", additionalText]; } if (nil == [c stringFromEventType: eventType]) { [self release]; [NSException raise: NSInvalidArgumentException format: @"bad event type (%d)", eventType]; } if (nil == [c stringFromSeverity: perceivedSeverity]) { [self release]; [NSException raise: NSInvalidArgumentException format: @"bad severity (%d)", perceivedSeverity]; } if (nil == [c stringFromProbableCause: probableCause]) { [self release]; [NSException raise: NSInvalidArgumentException format: @"bad probable cause (%d)", probableCause]; } /* Anything other than an unknown probable cause must correspond to a * known event type, but an unknown probable cause may match any event. */ if (EcAlarmProbableCauseUnknown != probableCause) { _eventType = [c eventTypeFromProbableCause: probableCause]; if (_eventType != eventType) { [self release]; [NSException raise: NSInvalidArgumentException format: @"missmatch of event type and probable cause"]; } } if (nil != (self = [super init])) { _notificationID = 0; _eventType = eventType; _perceivedSeverity = perceivedSeverity; _probableCause = probableCause; _trendIndicator = 0; ASSIGNCOPY(_managedObject, managedObject); ASSIGNCOPY(_eventDate, eventDate); ASSIGNCOPY(_specificProblem, specificProblem); ASSIGNCOPY(_proposedRepairAction, proposedRepairAction); ASSIGNCOPY(_additionalText, additionalText); } return self; } - (id) initWithCoder: (NSCoder*)aCoder { int version = [aCoder versionForClassName: @"EcAlarm"]; if (version < 2) { [aCoder decodeValuesOfObjCTypes: "iiiii@@@@@@", &_eventType, &_notificationID, &_perceivedSeverity, &_probableCause, &_trendIndicator, &_managedObject, &_eventDate, &_firstEventDate, &_specificProblem, &_proposedRepairAction, &_additionalText]; } else { [aCoder decodeValuesOfObjCTypes: "iiiii@@@@@@@", &_eventType, &_notificationID, &_perceivedSeverity, &_probableCause, &_trendIndicator, &_managedObject, &_eventDate, &_firstEventDate, &_specificProblem, &_proposedRepairAction, &_additionalText, &_userInfo]; } return self; } /* Return YES if the two instances are equal according to the correlation * rules, NO otherwise. */ - (BOOL) isEqual: (id)other { if (other == self) { return YES; } if (NO == [other isKindOfClass: [EcAlarm class]]) { return NO; } if (NO == [[other managedObject] isEqual: _managedObject]) { return NO; } if (_notificationID > 0 && [other notificationID] == _notificationID) { /* We have a notificationID set ... if both have the same notification * ID then they are the same. */ return YES; } /* The correlation rule normally is: * Same managed object * same event type * same probable cause * same specific problem */ if ([other eventType] == _eventType && [other probableCause] == _probableCause && [[other specificProblem] isEqual: _specificProblem]) { return YES; } return NO; } - (NSString*) managedObject { return _managedObject; } - (NSString*) moComponent { NSArray *s = [_managedObject componentsSeparatedByString: @"_"]; return [s objectAtIndex: 3]; } - (NSString*) moHost { NSArray *s = [_managedObject componentsSeparatedByString: @"_"]; return [s objectAtIndex: 0]; } - (NSString*) moInstance { NSArray *s = [_managedObject componentsSeparatedByString: @"_"]; return [s objectAtIndex: 2]; } - (NSString*) moProcess { NSArray *s = [_managedObject componentsSeparatedByString: @"_"]; return [s objectAtIndex: 1]; } - (int) notificationID { return _notificationID; } - (EcAlarmSeverity) perceivedSeverity { return _perceivedSeverity; } - (NSString*) proposedRepairAction { return _proposedRepairAction; } - (EcAlarmProbableCause) probableCause { return _probableCause; } - (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder { return self; } - (void) setDelay: (uint8_t)delay { if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } _delay = delay; } - (void) setExtra: (void*)extra { if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } _extra = extra; } - (void) setFirstEventDate: (NSDate*)firstEventDate { if (nil != firstEventDate && NO == [firstEventDate isKindOfClass: [NSDate class]]) { [NSException raise: NSInvalidArgumentException format: @"[%@-%@] bad argument '%@'", NSStringFromClass([self class]), NSStringFromSelector(_cmd), firstEventDate]; } if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } ASSIGNCOPY(_firstEventDate, firstEventDate); } - (void) setNotificationID: (int)notificationID { if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } _notificationID = notificationID; } - (void) setTrendIndicator: (EcAlarmTrend)trendIndicator { if (nil == [[self class] stringFromTrend: trendIndicator]) { [NSException raise: NSInvalidArgumentException format: @"[%@-%@] bad argument '%d'", NSStringFromClass([self class]), NSStringFromSelector(_cmd), trendIndicator]; } if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } _trendIndicator = trendIndicator; } - (void) setUserInfo: (NSDictionary*)userInfo { if (YES == _frozen) { [NSException raise: NSInternalInconsistencyException format: @"[%@-%@] called for frozen instance", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } ASSIGNCOPY(_userInfo, userInfo); } - (NSString*) specificProblem { return _specificProblem; } - (EcAlarmTrend) trendIndicator { return _trendIndicator; } - (NSDictionary*) userInfo { return _userInfo; } @end @implementation EcAlarm (Convenience) + (EcAlarm*) clear: (NSString*)componentName cause: (EcAlarmProbableCause)probableCause problem: (NSString*)specificProblem { NSString *managedObject; EcAlarmEventType eventType; managedObject = EcMakeManagedObject(nil, nil, componentName); eventType = [self eventTypeFromProbableCause: probableCause]; return [self alarmForManagedObject: managedObject at: nil withEventType: eventType probableCause: probableCause specificProblem: specificProblem perceivedSeverity: EcAlarmSeverityCleared proposedRepairAction: nil additionalText: nil]; } + (EcAlarm*) raise: (NSString*)componentName cause: (EcAlarmProbableCause)probableCause problem: (NSString*)specificProblem severity: (EcAlarmSeverity)perceivedSeverity action: (NSString*)proposedRepairAction,... { NSString *managedObject; EcAlarmEventType eventType; NSString *mesg; va_list ap; NSAssert(EcAlarmSeverityCleared != perceivedSeverity, NSInvalidArgumentException); managedObject = EcMakeManagedObject(nil, nil, componentName); eventType = [self eventTypeFromProbableCause: probableCause]; va_start (ap, proposedRepairAction); mesg = [NSString stringWithFormat: proposedRepairAction arguments: ap]; va_end (ap); return [self alarmForManagedObject: managedObject at: nil withEventType: eventType probableCause: probableCause specificProblem: specificProblem perceivedSeverity: perceivedSeverity proposedRepairAction: mesg additionalText: nil]; } @end