Whamcloud - gitweb
Initial import of lustre-snmp module.
authorjacob <jacob>
Thu, 14 Jul 2005 21:00:40 +0000 (21:00 +0000)
committerjacob <jacob>
Thu, 14 Jul 2005 21:00:40 +0000 (21:00 +0000)
snmp/Lustre-MIB.txt [new file with mode: 0644]
snmp/Makefile.am [new file with mode: 0644]
snmp/README.install [new file with mode: 0644]
snmp/autoconf/Makefile.am [new file with mode: 0644]
snmp/autoconf/lustre-snmp.m4 [new file with mode: 0644]
snmp/lustre-snmp-trap.c [new file with mode: 0644]
snmp/lustre-snmp-trap.h [new file with mode: 0644]
snmp/lustre-snmp-util.c [new file with mode: 0644]
snmp/lustre-snmp-util.h [new file with mode: 0644]
snmp/lustre-snmp.c [new file with mode: 0644]
snmp/lustre-snmp.h [new file with mode: 0644]

diff --git a/snmp/Lustre-MIB.txt b/snmp/Lustre-MIB.txt
new file mode 100644 (file)
index 0000000..db662d1
--- /dev/null
@@ -0,0 +1,966 @@
+--
+-- Lustre Filesystem MIB Module
+--
+
+LUSTRE-MIB DEFINITIONS ::= BEGIN
+    IMPORTS
+        MODULE-IDENTITY, OBJECT-TYPE, enterprises, Integer32,
+        Unsigned32, Counter64
+            FROM SNMPv2-SMI
+        DisplayString, TruthValue, RowStatus
+            FROM SNMPv2-TC;
+
+lustreMIB MODULE-IDENTITY
+    LAST-UPDATED "200505150100Z"
+    ORGANIZATION "Cluster Filesystems, Inc."
+    CONTACT-INFO
+    "         info@clusterfs.com
+
+    Postal: Cluster File Systems, Inc.
+            110 Capen St
+            Medford, MA 02155
+            USA"
+
+    DESCRIPTION
+        "Management information for the Lustre parallel filesystem."
+
+    ::= { clusterFileSystemsSNMP 1 }
+
+--============================================================================
+--
+-- Administrative assignments
+--
+--============================================================================
+
+clusterFileSystems     OBJECT IDENTIFIER ::= { enterprises 13140 }
+clusterFileSystemsSNMP OBJECT IDENTIFIER ::= { clusterFileSystems 2 }
+
+lustreMgmtTraps        OBJECT IDENTIFIER ::= { lustreMIB 0 }
+systemInformation      OBJECT IDENTIFIER ::= { lustreMIB 1 }
+objectStorageTargets   OBJECT IDENTIFIER ::= { lustreMIB 2 }
+objectStorageClients   OBJECT IDENTIFIER ::= { lustreMIB 3 }
+metaDataServers        OBJECT IDENTIFIER ::= { lustreMIB 4 }
+metaDataClients        OBJECT IDENTIFIER ::= { lustreMIB 5 }
+lustreClients          OBJECT IDENTIFIER ::= { lustreMIB 6 }
+logicalObjectVolume    OBJECT IDENTIFIER ::= { lustreMIB 7 }
+lustreLDLM             OBJECT IDENTIFIER ::= { lustreMIB 8 }
+
+
+--============================================================================
+--
+-- System Information
+--
+--============================================================================
+
+sysVersion OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre version string."
+    ::= { systemInformation 1 }
+    
+sysKernelVersion OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre kernel version string."
+    ::= { systemInformation 2 }
+    
+sysHealthCheck OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre kernel health check string. Contains 'healthy' or
+         'NOT healthy' plus descriptive information on the failure"
+    ::= { systemInformation 3 }    
+    
+sysStatus OBJECT-TYPE
+    SYNTAX INTEGER {
+        -- The following two values are states:
+        -- they may be read, or written
+        online(1),
+        offline(2),
+        -- The following two values are states:
+        -- they may be read, but not written
+        onlinePending(3),
+        offlinePending(4),
+        -- The following value is an action:
+        -- this value may be written, but never read.
+        restart(5)
+    }
+    MAX-ACCESS read-write
+    STATUS current
+    DESCRIPTION
+        "The sysStatus variable is used to manage the overall state of the
+        Lustre components on a system.  It has five defined values:
+
+            - 'online', which indicates that all of the configured
+            Lustre components have been successfully activated;
+
+            - 'offline', which indicates that all of the Lustre
+            components have been successfully deactivated;
+
+            - 'onlinePending', which indicates one or more failures
+            occurred in transitioning to the 'online' state;
+
+            - 'offlinePending', which indicates one or more failures
+            occurred in transitioning to the 'offline' state;
+
+            - 'restart', which is supplied by a management station
+            wishing to transition first to the 'offline' state, and
+            then to the 'online' state.
+
+        Only three of these five values may be specified in a
+        management protocol set operation: 'online', 'offline',
+        'restart'.  Only four of the five values will be returned in
+        response to a management protocol retrieval operation:
+        'online', 'offline', 'onlinePending', 'offlinePending'."
+
+    ::= { systemInformation 4 }    
+
+--============================================================================
+--
+-- Object Storage Targets
+--
+--============================================================================
+
+osdNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of Object Storage Devices on a OST system."
+    ::= { objectStorageTargets 1 }
+
+osdTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF OsdEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the Object Storage Devices available on a OST system.
+         The number of entries in this table is available in osdNumber."
+    ::= { objectStorageTargets 2 }
+
+osdEntry OBJECT-TYPE
+    SYNTAX OsdEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information an Object Storage Device on a OST
+         system."
+    INDEX { osdIndex }
+    ::= { osdTable 1 }
+
+OsdEntry ::=
+    SEQUENCE {
+        osdIndex         Unsigned32,
+        osdUUID          DisplayString,
+        osdCommonName    DisplayString,
+        osdCapacity      Counter64,
+        osdFreeCapacity  Counter64,
+        osdObjects       Counter64,
+        osdFreeObjects   Counter64
+    }
+
+osdIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of Object Storage Devices on a OST system."
+    ::= { osdEntry 1 }
+
+osdUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universally Unique Identifier (UUID) for the Object
+         Storage Device."
+    ::= { osdEntry 2 }
+
+osdCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Its the instance name given by Lustre proc subsystem for
+         each of the object storage device."
+    ::= { osdEntry 3 }
+
+osdCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The capacity of the Object Storage Device in bytes."
+    ::= { osdEntry 4 }
+
+osdFreeCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The remaining free capacity of the Object Storage Device in bytes."
+    ::= { osdEntry 5 }
+
+osdObjects OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The maximum number of objects that may be stored in an Object
+         Storage Device."
+    ::= { osdEntry 6 }
+
+osdFreeObjects OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of unused objects on an Object Storage Device."
+    ::= { osdEntry 7 }
+
+--============================================================================
+--
+-- Object Storage Client
+--
+--============================================================================
+
+oscNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of Object Storage Clients."
+    ::= { objectStorageClients 1 }
+
+oscTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF OscEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the Object Storage Clients available.
+         The number of entries in this table is available in oscNumber."
+    ::= { objectStorageClients 2 }
+
+oscEntry OBJECT-TYPE
+    SYNTAX OscEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information an Object Storage Clients."
+    INDEX { oscIndex }
+    ::= { oscTable 1 }
+
+OscEntry ::=
+    SEQUENCE {
+        oscIndex         Unsigned32,
+        oscUUID          DisplayString,
+        oscCommonName    DisplayString,
+        oscOSTServerUUID DisplayString,
+        oscCapacity      Counter64,
+        oscFreeCapacity  Counter64,
+        oscObjects       Counter64,
+        oscFreeObjects   Counter64
+    }
+
+oscIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of Object Storage Clients."
+    ::= { oscEntry 1 }
+
+oscUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universally Unique Identifier (UUID) for the Object
+         Storage Device."
+    ::= { oscEntry 2 }
+
+oscCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Its the instance name given by Lustre proc subsystem for
+         each of the object storage device."
+    ::= { oscEntry 3 }
+    
+oscOSTServerUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Object Storage Target UUID accessed by Object Storage Client.
+         This string also contains a state name, and possibly a DEACTIVATED flag." 
+    ::= { oscEntry 4 }       
+
+oscCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The capacity of the Object Storage Client in bytes."
+    ::= { oscEntry 5 }
+
+oscFreeCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The remaining free capacity of the Object Storage Client in bytes."
+    ::= { oscEntry 6 }
+
+oscObjects OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The maximum number of objects that may be stored in an Object
+         Storage Client."
+    ::= { oscEntry 7 }
+
+oscFreeObjects OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of unused objects on an Object Storage Client."
+    ::= { oscEntry 8 }
+
+--============================================================================
+--
+-- Metadata Servers
+--
+--============================================================================
+
+mddNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of Metadata Devices on a MDS system."
+    ::= { metaDataServers 1 }
+
+mddTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF MddEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the Meta Data Devices available on a MDS system.
+         The number of entries in this table is available in mddNumber."
+    ::= { metaDataServers 2 }
+
+mddEntry OBJECT-TYPE
+    SYNTAX MddEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information an Meta Data Device on a MDS system."
+    INDEX { mddIndex }
+    ::= { mddTable 1 }
+
+MddEntry ::=
+    SEQUENCE {
+        mddIndex        Unsigned32,
+        mddUUID         DisplayString,
+        mddCommonName   DisplayString,
+        mddCapacity     Counter64,
+        mddFreeCapacity Counter64,
+        mddFiles        Counter64,
+        mddFreeFiles    Counter64
+    }
+
+mddIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of Meta Data Devices on a MDS system."
+    ::= { mddEntry 1 }
+
+mddUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universal Unique Identifier (UUID) for the Meta Data
+         Device."
+    ::= { mddEntry 2 }
+
+mddCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The common name of the Meta Data Device.
+         Its the instance name given by Lustre proc subsystem for
+         each of the Meta Data Device."
+    ::= { mddEntry 3 }
+
+mddCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The capacity of the Meta Data Device in bytes."
+    ::= { mddEntry 4 }
+
+mddFreeCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The remaining free capacity of the Meta Data Device in bytes."
+    ::= { mddEntry 5 }
+
+mddFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The maximum number of files that may be stored on a Meta Data
+         Device."
+    ::= { mddEntry 6 }
+
+mddFreeFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of unused files on a Meta Data Device."
+    ::= { mddEntry 7 }
+  
+    
+--============================================================================
+--
+-- Metadata Clients
+--
+--============================================================================
+
+mdcNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of Metadata Clients."
+    ::= { metaDataClients 1 }
+
+mdcTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF MdcEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the Meta Data Clients.
+         The number of entries in this table is available in mdcNumber."
+    ::= { metaDataClients 2 }
+
+mdcEntry OBJECT-TYPE
+    SYNTAX MdcEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information an Meta Data Client."
+    INDEX { mdcIndex }
+    ::= { mdcTable 1 }
+
+MdcEntry ::=
+    SEQUENCE {
+        mdcIndex            Unsigned32,
+        mdcUUID             DisplayString,
+        mdcCommonName       DisplayString,
+        mdcMDSServerUUID    DisplayString,
+        mdcCapacity         Counter64,
+        mdcFreeCapacity     Counter64,
+        mdcFiles            Counter64,
+        mdcFreeFiles        Counter64
+    }
+
+mdcIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of Meta Data Client."
+    ::= { mdcEntry 1 }
+
+mdcUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universal Unique Identifier (UUID) for the Meta Data Client."
+    ::= { mdcEntry 2 }
+
+mdcCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The common name of the Meta Data Client.
+         Its the instance name given by Lustre proc subsystem for
+         each of the Meta Data Client."
+    ::= { mdcEntry 3 }
+    
+mdcMDSServerUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Meta data server UUID accessed by Metadata Client.
+         This string also contains a state name, and possibly a DEACTIVATED flag." 
+    ::= { mdcEntry 4 }    
+
+mdcCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The capacity of the Meta Data Client in bytes."
+    ::= { mdcEntry 5 }
+
+mdcFreeCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The remaining free capacity of the Meta Data Client in bytes."
+    ::= { mdcEntry 6 }
+
+mdcFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The maximum number of files that may be stored on a Meta Data Client."
+    ::= { mdcEntry 7 }
+
+mdcFreeFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of unused files on a Meta Data Client."
+    ::= { mdcEntry 8 }
+   
+--============================================================================
+--
+-- Lustre Clients
+--
+--============================================================================
+
+cliMountNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "The number of Lustre mounts that are currently on a client system." 
+    ::= { lustreClients 1 }
+
+cliMountTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF CliMountEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the Lustre file system mount points and their
+         configurations. The current number of entries is specified by
+         cliMountNumber."
+    ::= { lustreClients 2 }
+
+cliMountEntry OBJECT-TYPE
+    SYNTAX CliMountEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Information about a single Lustre file system mount point."
+    INDEX { cliIndex }
+    ::= { cliMountTable 1 }
+
+CliMountEntry ::=
+    SEQUENCE {
+        cliIndex           Unsigned32,
+        cliUUID            DisplayString,
+        cliCommonName      DisplayString,
+        cliMDSUUID         DisplayString,
+        cliMDSCommonName   DisplayString,
+        cliUsesLOV         TruthValue,
+        cliLOVUUID         DisplayString,
+        cliLOVCommonName   DisplayString
+    }
+
+cliIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of Lustre file system mount points on a
+         client system."
+    ::= { cliMountEntry 1 }
+
+cliUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universal Unique Identifier (UUID) for a Lustre
+         file system mount point."
+    ::= { cliMountEntry 2 }
+
+cliCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Its the instance name given by Lustre proc subsystem for
+         each of the Lustre client mount point."
+    ::= { cliMountEntry 3 }
+
+cliMDCUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The UUID of the Metadata Client to which a Lustre file system
+         mount point is connected."
+    ::= { cliMountEntry 4 }
+
+cliMDCCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "This is the name of the Metadata Client to which a Lustre client
+         file system mount point is connected."
+    ::= { cliMountEntry 5 }
+
+cliUsesLOV OBJECT-TYPE
+    SYNTAX TruthValue
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "This variable is true(1) if a Lustre file system mount point
+        is using a Logical Object volume (LOV), and false(2) otherwise."
+    ::= { cliMountEntry 6 }
+    
+cliLOVUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The UUID of the LOV to which a Lustre file system
+         mount point is connected."
+    ::= { cliMountEntry 7 }
+
+cliLOVCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "This is the name of the LOV to which a Lustre client
+         file system mount point is connected."
+    ::= { cliMountEntry 8 }    
+
+  
+--============================================================================
+--
+-- Logical Object Volume
+--
+--============================================================================
+
+lovNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of LOV instances."
+    ::= { logicalObjectVolume 1 }
+
+lovTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF LovEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the statistics for LOV instances available on
+         a Lustre configured node."
+    ::= { logicalObjectVolume 2 }
+
+lovEntry OBJECT-TYPE
+    SYNTAX LovEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information on LOV stats for all LOV instances
+         available on a Lustre configured node."
+    INDEX { lovIndex }
+    ::= { lovTable 1 }
+
+LovEntry ::=
+    SEQUENCE {
+        lovIndex         Unsigned32,
+        lovUUID          DisplayString,
+        lovCommonName    DisplayString,        
+        lovNumOBD        Unsigned32,
+        lovNumActiveOBD  Unsigned32,
+        lovCapacity      Counter64,
+        lovFreeCapacity  Counter64,
+        lovFiles         Counter64,
+        lovFreeFiles     Counter64,
+        lovStripeCount   Unsigned32,
+        lovStripeOffset  Unsigned32,
+        lovStripeSize    Unsigned32,
+        lovStripeType    Unsigned32
+    }
+
+lovIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of LOV stats for LOV instances available
+         on a Lustre configured system."
+    ::= { lovEntry 1 }
+    
+lovUUID OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The Lustre Universally Unique Identifier (UUID) for the LOV."
+    ::= { lovEntry 2 }
+
+lovCommonName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Its the instance name given by Lustre proc subsystem for
+         each of the LOVs."
+    ::= { lovEntry 3 }    
+    
+lovNumOBD OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of OBDs."
+    ::= { lovEntry 4 }
+    
+
+lovNumActiveOBD OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The name of the target OBDs."
+    ::= { lovEntry 5 }
+    
+    
+lovCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The capacity of the LOV in bytes."
+    ::= { lovEntry 6 }
+
+lovFreeCapacity OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The remaining free capacity of the LOV in bytes."
+    ::= { lovEntry 7 }
+
+lovFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The maximum number of files that may be stored on a LOV."
+    ::= { lovEntry 8 }
+
+lovFreeFiles OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of unused files on a LOV."
+    ::= { lovEntry 9 }
+    
+lovStripeCount OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of stripes on a LOV."
+    ::= { lovEntry 10 }    
+    
+lovStripeOffset OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The stripe offset on a LOV."
+    ::= { lovEntry 11 }    
+        
+lovStripeSize OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The stripe size on a LOV."
+    ::= { lovEntry 12 }     
+    
+lovStripeType OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The stripe type on a LOV."
+    ::= { lovEntry 13 }         
+   
+--============================================================================
+--
+-- Lustre Distributed Lock Manager
+--
+--============================================================================
+
+ldlmNumber OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The number of LDLM namespaces (Also its the number of instances
+         in a LDLM table)"
+    ::= { lustreLDLM 1 }
+
+ldlmTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF LdlmEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "A table listing the statistics for LDLM namespaces available on
+         a Lustre configured node."
+    ::= { lustreLDLM 2 }
+
+ldlmEntry OBJECT-TYPE
+    SYNTAX LdlmEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Table entry with information LDLM stats for all LDLM namespaces
+         available on a Lustre configured node."
+    INDEX { ldlmIndex }
+    ::= { ldlmTable 1 }
+
+LdlmEntry ::=
+    SEQUENCE {
+        ldlmIndex           Unsigned32,
+        ldlmNameSpace       DisplayString,
+        ldlmLockCount       Unsigned32,
+        ldlmUnusedLockCount Unsigned32,
+        ldlmResourceCount   Unsigned32
+    }
+
+ldlmIndex OBJECT-TYPE
+    SYNTAX Unsigned32 (1..2147483647)
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+        "Index into the table of LDLM stats for LDLM namespaces available
+         on a Lustre configured system."
+    ::= { ldlmEntry 1 }
+
+ldlmNameSpace OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The name of the particular LDLM namespace."
+    ::= { ldlmEntry 2 }
+
+ldlmLockCount OBJECT-TYPE
+    SYNTAX Unsigned32 
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Active Lock count of particular LDLM namespace."
+    ::= { ldlmEntry 3 }
+    
+ldlmUnusedLockCount OBJECT-TYPE
+    SYNTAX Unsigned32 
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Unused Lock count of particular LDLM namespace."
+    ::= { ldlmEntry 4 }
+    
+ldlmResourceCount OBJECT-TYPE
+    SYNTAX Unsigned32 
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Resource count of particular LDLM namespace."
+    ::= { ldlmEntry 5 }    
+
+--============================================================================
+--
+-- Lustre Management Traps
+--
+--============================================================================
+
+
+lustrePortalsCatastropeTrap NOTIFICATION-TYPE
+    OBJECTS {
+            lustrePortalsCatastropeReasonString
+    }
+    STATUS current
+    DESCRIPTION
+        "The Lustre service Failure traps sent to management station in
+         case of Portals Catastrophe."
+    ::= { lustreMgmtTraps 1 }
+    
+lustrePortalsCatastropeReasonString OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The portals catastrophe description string."
+    ::= { lustreMgmtTraps 2 }     
+    
+lustreOBDUnhealthyTrap NOTIFICATION-TYPE
+    OBJECTS {
+            lustreOBDNameString,
+            lustreOBDUnhealthyReasonString
+    }
+    STATUS current
+    DESCRIPTION
+        "The Lustre service Failure traps sent to management station in
+         on OBD health check failure."
+    ::= { lustreMgmtTraps 3 }    
+   
+lustreOBDNameString OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The health status string."
+    ::= { lustreMgmtTraps 4 }    
+    
+lustreOBDUnhealthyReasonString OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "The health status string."
+    ::= { lustreMgmtTraps 5 }        
+
+END
diff --git a/snmp/Makefile.am b/snmp/Makefile.am
new file mode 100644 (file)
index 0000000..c1ee04f
--- /dev/null
@@ -0,0 +1,19 @@
+agent_PROGRAMS  := lustresnmp.so
+mib_DATA := Lustre-MIB.txt
+
+lustresnmp_so_SOURCES := \
+       lustre-snmp.c           \
+       lustre-snmp.h           \
+       lustre-snmp-trap.c      \
+       lustre-snmp-trap.h      \
+       lustre-snmp-util.c      \
+       lustre-snmp-util.h
+
+lustresnmp_so_LDADD := $(NET_SNMP_LIBS)
+lustresnmp_so_CFLAGS := $(NET_SNMP_CFLAGS)
+lustresnmp_so_LDFLAGS := -fPIC -shared
+
+SUBDIRS :=
+DIST_SUBDIRS := autoconf
+
+EXTRA_DIST := $(mib_DATA)
diff --git a/snmp/README.install b/snmp/README.install
new file mode 100644 (file)
index 0000000..652c4d5
--- /dev/null
@@ -0,0 +1,9 @@
+Steps for installation:
+
+Update /etc/snmp/snmpd.conf appending the following line:
+
+dlmod lustresnmp /usr/lib/lustre/snmp/lustresnmp.so
+
+Or the appropriate path to the snmp module.
+
+Then, restart the snmpd daemon.
diff --git a/snmp/autoconf/Makefile.am b/snmp/autoconf/Makefile.am
new file mode 100644 (file)
index 0000000..2bb7693
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST := lustre-snmp.m4
diff --git a/snmp/autoconf/lustre-snmp.m4 b/snmp/autoconf/lustre-snmp.m4
new file mode 100644 (file)
index 0000000..2ca0f46
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# LS_CONFIGURE
+#
+# configure bits for lustre-snmp
+#
+AC_DEFUN([LS_CONFIGURE],
+[AC_MSG_CHECKING([whether to try to build SNMP support])
+AC_ARG_ENABLE([snmp],
+       AC_HELP_STRING([--enable-snmp],
+                      [require SNMP support (default=auto)]),
+       [],[enable_snmp='auto'])
+AC_MSG_RESULT([$enable_snmp])
+
+if test x$enable_snmp != xno ; then
+       AC_CHECK_PROG([NET_SNMP_CONFIG], [net-snmp-config], [net-snmp-config], [])
+       if test "$NET_SNMP_CONFIG" ; then
+               NET_SNMP_CFLAGS=$($NET_SNMP_CONFIG --base-cflags)
+               NET_SNMP_LIBS=$($NET_SNMP_CONFIG --agent-libs)
+
+               CPPFLAGS_save="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $NET_SNMP_CFLAGS"
+
+               LIBS_save="$LIBS"
+               LIBS="$LIBS $NET_SNMP_LIBS"
+
+               AC_CHECK_HEADER([net-snmp/net-snmp-config.h],[
+                       AC_CHECK_FUNC([register_mib],[SNMP_SUBDIR="snmp"],[
+                               LIBS="$LIBS -lwrap"
+                               NET_SNMP_LISB="$NET_SNMP_LIBS -lwrap"
+                               # fail autoconf's cache
+                               unset ac_cv_func_register_mib
+                               AC_CHECK_FUNC([register_mib],[SNMP_SUBDIR="snmp"])
+                       ])
+               ])
+
+               LIBS="$LIBS_save"
+               CPPFLAGS="$CPPFLAGS_save"
+       fi
+       AC_MSG_CHECKING([for SNMP support])
+       if test "$SNMP_SUBDIR" ; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no (see config.log for errors)])
+               if test x$enable_snmp = xyes ; then
+                       AC_MSG_ERROR([SNMP support was requested, but unavailable])
+               fi
+       fi
+fi
+
+agentdir='${pkglibdir}/snmp'
+mibdir='${pkgdatadir}/snmp/mibs'
+
+AC_SUBST(SNMP_SUBDIR)
+AC_SUBST(NET_SNMP_CFLAGS)
+AC_SUBST(NET_SNMP_LIBS)
+AC_SUBST(agentdir)
+AC_SUBST(mibdir)
+])
+
+#
+# LS_CONDITIONALS
+#
+# AM_CONDITIONALs for lustre-snmp
+#
+AC_DEFUN([LS_CONDITIONALS],
+[
+])
+
+#
+# LS_CONFIG_FILE
+#
+# files that should be generated with AC_OUTPUT
+#
+AC_DEFUN([LS_CONFIG_FILES],
+[AC_CONFIG_FILES([
+snmp/Makefile
+snmp/autoconf/Makefile
+])
+])
diff --git a/snmp/lustre-snmp-trap.c b/snmp/lustre-snmp-trap.c
new file mode 100644 (file)
index 0000000..7caf5ce
--- /dev/null
@@ -0,0 +1,532 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *   include important headers
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+/*
+ *  include our .h file
+ */ 
+
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "lustre-snmp-util.h"
+
+/**************************************************************************
+ * Constants
+ *************************************************************************/
+
+#define DEFAULT_POLL_INTERVAL_SECONDS   60
+#define POLL_INTERVAL_ENV_VAR           "LSNMP_POLL_INTERVAL"
+#define SNMP_HEALTH_CHECK_TEST_FILE     "LSNMP_HEALTH_CHECK_TEST_FILE"
+
+/**************************************************************************
+ * Trap OIDS
+ *************************************************************************/
+
+static oid objid_snmptrap[] =                       
+    { 1,3,6,1,6,3,1,1,4,1,0};
+static oid lustre_portals_trap[] = 
+    { 1,3,6,1,4,1,13140,2,1,0,1};
+static oid lustre_portals_trap_string[]= 
+    { 1,3,6,1,4,1,13140,2,1,0,2};
+static oid lustre_unhealthy_trap[] = 
+    { 1,3,6,1,4,1,13140,2,1,0,3};
+static oid lustre_unhealthy_trap_device_name_string[]= 
+    { 1,3,6,1,4,1,13140,2,1,0,4};
+static oid lustre_unhealthy_trap_reason_string[]= 
+    { 1,3,6,1,4,1,13140,2,1,0,5};
+
+/**************************************************************************
+ * Data structures
+ *************************************************************************/
+
+typedef struct obd_unhealthy_entry_struct{
+
+    /*1-if seen as part of the the is_unhealthy scan, otherwise 0*/
+    int seen;                         
+
+    /*single linked list pointer*/
+    struct obd_unhealthy_entry_struct *next; 
+
+    /*obdname - variable size*/
+    char name[0];                     
+
+}obd_unhealthy_entry;
+
+/**************************************************************************
+ * Local functions
+ *************************************************************************/
+
+int get_poll_interval_seconds();
+void health_poll_worker(unsigned int registration_number, void *clientarg);
+void send_portals_catastrophe_trap(char *reason_string);
+void send_obd_unhealthy_trap(char *obd_name,char *reason_string);
+int is_obd_newly_unhealthy(const char* obd_name);
+void obd_unhealthy_scan(void);
+void health_entry_parser(void);
+
+/**************************************************************************
+ * Global variables
+ *************************************************************************/
+
+static int g_sent_portals_catastrophe = 0;
+static obd_unhealthy_entry* g_obd_unhealthy_list = NULL;
+static int g_poll_interval_seconds;
+static unsigned int g_registration_handle;
+static char *g_health_check_test_file = 0;
+
+/*****************************************************************************
+ * Function: initilize_trap_handler
+ *
+ * Description: Initlized the trap poll haalder.
+ *
+ * Input:   void
+ *
+ * Output:  Global g_poll_interval_seconds is set.
+ *
+ ****************************************************************************/
+void initilize_trap_handler(void)
+{
+    g_poll_interval_seconds = get_poll_interval_seconds();
+
+    g_registration_handle = snmp_alarm_register(g_poll_interval_seconds, 0, health_poll_worker, NULL);
+    if (g_registration_handle == 0)
+        report("%s %s: line %d %s", __FILE__, __FUNCTION__, __LINE__,
+            "snmp_alarm_register failed");
+            
+    DEBUGMSGTL(("lsnmpd","lsnmp alarm registered poll interval = %d seconds\n",g_poll_interval_seconds));
+    
+    g_health_check_test_file = getenv(SNMP_HEALTH_CHECK_TEST_FILE);    
+    if(g_health_check_test_file != 0)
+        DEBUGMSGTL(("lsnmpd","lsnmp health check test file set to  \'%s\'\n",g_health_check_test_file));
+}
+
+/*****************************************************************************
+ * Function: terminate_trap_handler
+ *
+ * Description: Terminate the trap poll haalder.
+ *
+ * Input:   void
+ *
+ * Output:  Global g_poll_interval_seconds is set.
+ *
+ ****************************************************************************/
+
+void terminate_trap_handler(void)
+{
+    snmp_alarm_unregister(g_registration_handle);
+}
+
+/*****************************************************************************
+ * Function: get_poll_interval_seconds
+ *
+ * Description: This function used to get the poll period for timer, which 
+ *              is used to read throughput values periodically.
+ * Input:   void
+ * Output:  Alarm period, default value(if env var not set) otherwise.
+ ****************************************************************************/
+
+int get_poll_interval_seconds()
+{
+    char *alarm_period;
+    int ret_val = DEFAULT_POLL_INTERVAL_SECONDS;
+
+    /* Get Alarm period for reading the Lustre client table. */
+
+    alarm_period = getenv(POLL_INTERVAL_ENV_VAR);
+    if (alarm_period != NULL) {
+        char *ptr = alarm_period;
+        while(isdigit(*ptr)) ptr++;
+
+        /* if we have only digits then conver it*/
+        if (*ptr == '\0') {
+            int time = atoi(alarm_period);
+            if (time > 0)
+                ret_val = time; /* Alarm period in seconds */
+        }
+    }
+    return ret_val;
+}
+
+/*****************************************************************************
+ * Function:  health_poll_worker
+ *
+ * Description: This is the routine registered to system timer for updating
+ *     the throughput values for all the clients and its respective osc(s).
+ *
+ * Input:  'registration_number` value obtained during the alarm registration
+ *         'clientarg' pointing to user defined data type.
+ * Output: void
+ *****************************************************************************/
+
+void health_poll_worker(unsigned int registration_number, void *clientarg)
+{
+    health_entry_parser();
+
+    /* Register the function again to call after lustre_alarm_period */
+    if (!snmp_alarm_register(g_poll_interval_seconds, 0, health_poll_worker, NULL)) {
+        report("%s %s:line %d %s", __FILE__, __FUNCTION__, __LINE__,
+               "snmp_alarm_register failed");
+    }
+}
+
+/*****************************************************************************
+ * Function:  health_entry_parser
+ *
+ * Description: This routine is called to parse the health_check entry
+ *              and send traps
+ * Input:  'None
+ * Output: void
+ *****************************************************************************/
+ void health_entry_parser(void)
+{
+    FILE    *fptr = NULL;
+    char string[MAX_LINE_SIZE];
+    int b_seen_portals_catastrophe = 0;
+    const char *filename =  g_health_check_test_file == 0 ? 
+            LUSTRE_PATH FILENAME_SYSHEALTHCHECK : 
+            g_health_check_test_file;
+    
+    /*DEBUGMSGTL(("lsnmpd","health_entry_parser(%s)\n",filename));*/
+
+    /* Open the file.  Use the test file env variable if
+       there is one */    
+    fptr = fopen(filename,"r");
+        
+    /* If the path is not found do nothing */
+    if( NULL == fptr)
+        return;
+       
+    while( NULL != fgets(string, sizeof(string), fptr)){
+        
+        /*DEBUGMSGTL(("lsnmpd","health_entry_parser() looking at = \'%s\'\n",string));*/
+       
+        /*
+         * First handle the portals catastrophe 
+         * Look for the string "LBUG"
+         */
+        if(0 == strncmp(string,"LBUG",4)){
+            /*
+             * If we haven't sent the catastrophe message yet
+             * send it now.  And keep track that we've sent it
+             */
+            if(!g_sent_portals_catastrophe){
+                send_portals_catastrophe_trap("LBUG");
+                g_sent_portals_catastrophe = 1;
+            }
+            b_seen_portals_catastrophe = 1;
+        }
+            
+        /*
+         * Now handle any of the OBD object failures
+         * look for "device <OBDNAME> reported unhealthy"
+         */
+        else if(0 == strncmp(string,"device ",7)){
+            char *obd_name = string+7;
+            char *space_after_obd_name;
+            
+            /*
+             * Now find the space after the obd name
+             * Again if there is no space we're in trouble
+             */
+            space_after_obd_name = strchr(obd_name,' ');
+            if(space_after_obd_name == 0)
+                break;
+
+            /*
+             * Null terminate the obd_name
+             */
+            *space_after_obd_name = 0;
+            
+            DEBUGMSGTL(("lsnmpd","Looking at obd=%s\n",obd_name));
+
+            /*
+             * If we haven't sent a trap for this one
+             * then send it now
+             */
+            if(is_obd_newly_unhealthy(obd_name))
+                send_obd_unhealthy_trap(obd_name,"unhealthy");
+        }
+    }        
+    
+    /* If we don't find it reset the catastrope flag*/            
+    if(!b_seen_portals_catastrophe && g_sent_portals_catastrophe)
+    {
+        DEBUGMSGTL(("lsnmpd","LBUG has been cleared\n"));
+        g_sent_portals_catastrophe = 0;
+    }
+                
+    /*
+     *  Any <OBDNAMES> that weren't queried above are now unhealthy. 
+     * Scan through and cleanup the newly healthy obds
+     */
+    obd_unhealthy_scan();
+    
+    fclose(fptr);
+}
+
+/*****************************************************************************
+ * Function:  send_portals_catastrophe_trap
+ *
+ * Description: Send the SNMP V2 trap
+ *
+ * Input:  'reason_string' the reason for the catastrope.
+ * Output: none
+ *****************************************************************************/
+void send_portals_catastrophe_trap(char *reason_string)
+{
+    /*
+     * Setup the trap variables.  
+     * It's a linked list of netsnmp_variable_list items.
+     */
+    netsnmp_variable_list var_trap[2];
+
+    DEBUGMSGTL(("lsnmpd","Sending portals catastrophe trap reason=%s\n",reason_string));
+
+    /* 
+     * Setup the first variable in the trap data. 
+     * Have it chain to another variable.
+     */
+    var_trap[0].next_variable = &var_trap[1];
+
+    /*The "name" must be the standard snmp "trap" OID.*/
+    var_trap[0].name = objid_snmptrap;
+    var_trap[0].name_length = sizeof(objid_snmptrap) / sizeof(oid);
+
+    /*But the data contained in this variable, is an OID that is the trap OID.*/
+    var_trap[0].type = ASN_OBJECT_ID;
+    var_trap[0].val.objid = lustre_portals_trap;
+    var_trap[0].val_len = sizeof(lustre_portals_trap);
+
+    /* 
+     * Setup the second variable in the trap data. 
+     * It is the last in the chain so set next to NULL
+     */
+    var_trap[1].next_variable = NULL;
+
+    /*The "name" is the OID of the portals trap reason strong*/
+    var_trap[1].name = lustre_portals_trap_string;
+    var_trap[1].name_length = sizeof(lustre_portals_trap_string) / sizeof(oid);
+
+    /*And the data is a octet string, that contains the actually reason string*/
+    var_trap[1].type = ASN_OCTET_STR;
+    var_trap[1].val.string = reason_string;
+    var_trap[1].val_len = strlen(reason_string);
+
+    /*And now send off the trap*/
+    send_v2trap(var_trap);
+}
+
+
+/*****************************************************************************
+ * Function:  send_obd_unhealthy_trap
+ *
+ * Description: Send the SNMP V2 trap
+ *
+ * Input:  'obd_name' the name of the obd
+ *         'reason_string' the reason for the catastrope.
+ * Output: none
+ *****************************************************************************/
+void send_obd_unhealthy_trap(char *obd_name,char *reason_string)
+{
+    /*
+     * Setup the trap variables.  
+     * It's a linked list of netsnmp_variable_list items.
+     */
+    netsnmp_variable_list var_trap[3];
+
+    DEBUGMSGTL(("lsnmpd","Sending OBD unhealthy trap obd=%s reason=%s\n",obd_name,reason_string));
+
+    /* 
+     * Setup the first variable in the trap data. 
+     * Have it chain to another variable.
+     */
+    var_trap[0].next_variable = &var_trap[1];
+
+    /*The "name" must be the standard snmp "trap" OID.*/
+    var_trap[0].name = objid_snmptrap;
+    var_trap[0].name_length = sizeof(objid_snmptrap) / sizeof(oid);
+
+    /*But the data contained in this variable, is an OID that is the trap OID.*/
+    var_trap[0].type = ASN_OBJECT_ID;
+    var_trap[0].val.objid = lustre_unhealthy_trap;
+    var_trap[0].val_len = sizeof(lustre_unhealthy_trap);
+
+    /* 
+     * Setup the second variable in the trap data. 
+     * Have it chain to another variable.
+     */
+    var_trap[1].next_variable = &var_trap[2];;
+
+    /*The "name" is the OID of the portals trap reason strong*/
+    var_trap[1].name = lustre_unhealthy_trap_device_name_string;
+    var_trap[1].name_length = sizeof(lustre_unhealthy_trap_device_name_string) / sizeof(oid);
+
+    /*And the data is a octet string, that contains the actually reason strong*/
+    var_trap[1].type = ASN_OCTET_STR;
+    var_trap[1].val.string = obd_name;
+    var_trap[1].val_len = strlen(obd_name);
+
+    /* 
+     * Setup the third variable in the trap data. 
+     * It is the last in the chain so set next to NULL
+     */
+    var_trap[2].next_variable = NULL;
+
+    /*The "name" is the OID of the portals trap reason strong*/
+    var_trap[2].name = lustre_unhealthy_trap_reason_string;
+    var_trap[2].name_length = sizeof(lustre_unhealthy_trap_reason_string) / sizeof(oid);
+
+    /*And the data is a octet string, that contains the actually reason strong*/
+    var_trap[2].type = ASN_OCTET_STR;
+    var_trap[2].val.string = reason_string;
+    var_trap[2].val_len = strlen(reason_string);
+
+    /*And now send off the trap*/
+    send_v2trap(var_trap);
+}
+
+
+/*****************************************************************************
+ * Function:  is_obd_newly_unhealthy
+ *
+ * Description: Deterime if the obd is going from health->unhealth
+ *              Also mark all unhealhy (new and old) as seen.
+ *
+ * Input:  'obd_name' the name of the obd
+ *
+ * Output: 1 if newly unhealthy 0 if previolsy unhealthy
+ *****************************************************************************/
+
+int is_obd_newly_unhealthy(const char* obd_name)
+{
+    /*for all elements in g_obd_unhealthy_list*/
+    obd_unhealthy_entry* walker;
+    obd_unhealthy_entry* entry;
+    int name_len;
+
+    for(walker = g_obd_unhealthy_list; walker != 0; walker = walker->next)
+    {
+        /*If the names match*/
+        if(0 == strcmp (walker->name,obd_name))
+        {
+            /* Commented out because it was just to noisy!
+             * DEBUGMSGTL(("lsnmpd","obd %s was already unhealthy\n",obd_name));
+             */
+            
+            /*Mark the entry as seen, and return that it was previously unhealthy*/
+            walker->seen =1;
+            return 0;
+        }
+    }
+
+    DEBUGMSGTL(("lsnmpd","obd %s is now unhealthy\n",obd_name));
+
+    /*We didn't find an entry so we need to create a new one. */
+    /*Calculate the obd_name length*/
+    name_len = strlen(obd_name)+1;
+
+    /*Allocate a new entry*/
+    entry = malloc(sizeof(*entry) + name_len);
+
+    /*Put this element at the front of the list*/
+    entry->next = g_obd_unhealthy_list;
+    g_obd_unhealthy_list = entry;
+
+    /*Mark it initially as seen*/
+    entry->seen = 1;
+
+    /*And copy the entry name*/
+    memcpy(entry->name,obd_name,name_len);
+
+    /*return this obd as newly unhealthy.*/
+    return 1;
+}
+
+
+/*****************************************************************************
+ * Function:  obd_unhealthy_scan
+ *
+ * Description: Deterime if any obd is going from unhealthy->healthy
+ *              Any of the obds that weren't "seen" by the 
+ *              is_obd_newly_unhealthy() pass are now health so 
+ *              remove them from the lists
+ *              Also clear all "seen" flags.
+ *
+ * Input:  None
+ * Output: None
+ *****************************************************************************/
+void obd_unhealthy_scan(void)
+{
+    /*fore all elements in g_obd_unhealthy_list*/
+    obd_unhealthy_entry* walker = g_obd_unhealthy_list;
+    obd_unhealthy_entry* prev = 0;
+    while(walker != 0)
+    {
+        /*remove any that was not seen as unhealthy the last time*/
+        if(walker->seen == 0)
+        {
+            /*Remove element from the list, but first fix up the walker pointer*/
+            obd_unhealthy_entry* temp = walker;
+
+            DEBUGMSGTL(("lsnmpd","obd %s is now healthy\n",walker->name));
+
+            walker = walker->next;
+
+            /*Now adjust the pointers to effectively remove this entry*/
+            if(prev == 0)
+                g_obd_unhealthy_list = walker;
+            else
+                prev->next = walker;
+
+            /*And free the pointer. */
+            free(temp);
+            /*walker and prev are correctly setup so we can go around the loop again.*/
+        }
+
+        /*Mark all other entries as NOT seen for next pass through*/
+        else 
+        {
+            walker->seen = 0;
+            /*Go onto the next entry*/
+            prev = walker;
+            walker = walker->next;
+        }
+    }
+}
diff --git a/snmp/lustre-snmp-trap.h b/snmp/lustre-snmp-trap.h
new file mode 100644 (file)
index 0000000..ce82324
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LUSTRE_SNMP_TRAP_H
+#define LUSTRE_SNMP_TRAP_H
+
+extern void initilize_trap_handler(void);
+extern void terminate_trap_handler(void);
+
+#endif
diff --git a/snmp/lustre-snmp-util.c b/snmp/lustre-snmp-util.c
new file mode 100644 (file)
index 0000000..8048f2d
--- /dev/null
@@ -0,0 +1,652 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *   include important headers
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+/*
+ *  include our .h file
+ */ 
+
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "lustre-snmp-util.h"
+
+/*********************************************************************
+ * Function:    get_file_list
+ *
+ * Description: For the given valid directory  path, returns the list
+ *              all directories or files in that path.
+ *
+ * Input:   'dirname' the directory path.
+ *          'file_type' if this takes the value DIR_TYPE then
+ *              returns the list of directories in that path.
+ *          If its of type FILE_TYPE then returns the list of files
+ *          in that path.
+ *          'count' pointer to number of elements returned in the
+ *          return string. 
+ *
+ * Output:  List of  directories/files in that path.
+ *
+ *********************************************************************/
+
+char *get_file_list(const char *dirname, int file_type, uint32_t *count)
+{
+
+    DIR           *pdir = NULL;
+    struct dirent *pdirent = NULL;
+    int           curr_offset = 0;
+    int           byte_count = 0;
+    int           file_count = 0;
+    char          *ret_str = NULL;
+    char          filename[MAX_PATH_SIZE];
+    int           cond1, cond2;
+
+    if ((dirname == NULL) || ((pdir = opendir(dirname)) == NULL )) {
+        if (dirname == NULL) {
+            report("%s %s:line %d %s", __FILE__, __FUNCTION__, __LINE__,
+                   "NULL directory is passed as parameter to funtion");
+        } else {
+            report("%s %s:line %d Error in opening the dir %s", __FILE__,
+                   __FUNCTION__, __LINE__, dirname);
+        }
+        if (count)
+            *count = 0;
+        return NULL;
+    }
+
+    while (1) {
+        if ((pdirent = readdir(pdir)) == NULL)
+            break;
+
+        /* Skip over '.' and '..' directores */
+        if ((pdirent->d_name[0] == '.') ||
+            !strcmp(pdirent->d_name, FILENAME_NUM_REF))
+            continue;
+        
+        sprintf(filename, "%s/%s", dirname, pdirent->d_name);
+        cond1 = (file_type == FILE_TYPE) && is_directory(filename);
+        cond2 = (file_type == DIR_TYPE) && (!is_directory(filename));
+
+        if (cond1 || cond2)
+            continue;
+
+        /* Calculate the number of bytes for this new entry.*/                    
+        byte_count += strlen(pdirent->d_name) + 1;
+        file_count++;
+    }
+    if (count)
+        *count = file_count;
+    
+    if (file_count != 0) {
+        
+        /* need one extra one for the finall NULL terminator*/
+        if ((ret_str = (char *) malloc(byte_count + 1)) == NULL) {
+            report("get_file_list() failed to malloc(%d)",byte_count+1);
+            closedir(pdir);
+            return NULL;
+        }    
+        
+        rewinddir(pdir);
+        
+        while (file_count != 0) {
+            if ((pdirent = readdir(pdir)) == NULL)
+                break;
+
+            if ((pdirent->d_name[0] == '.') ||
+                !strcmp(pdirent->d_name, FILENAME_NUM_REF))
+                continue;
+            
+            sprintf(filename, "%s/%s", dirname, pdirent->d_name);
+            cond1 = (file_type == FILE_TYPE) && is_directory(filename);
+            cond2 = (file_type == DIR_TYPE) && (!is_directory(filename));
+
+            if (cond1 || cond2)
+                continue;
+
+            strcpy(ret_str + curr_offset, pdirent->d_name);
+            curr_offset = curr_offset + strlen(pdirent->d_name) + 1;
+            file_count--;
+        }
+        /* Put in the finall null terminator*/
+        ret_str[byte_count] = '\0';
+    }
+    closedir(pdir);
+    return ret_str;
+}
+
+
+/*********************************************************************
+ * Function:    is_directory
+ *
+ * Description: Checks if given filename is a directory or not.
+ *              all directories or files in that path.
+ *
+ * Input:   'filename' the directory path to be checked.
+ *
+ * Output:  Returns 1 if its a directory else 0.
+ *
+ *********************************************************************/
+
+int is_directory(const char *filename)
+{
+
+    struct stat statf;
+    int result;
+
+    result = stat(filename, &statf);
+    return ((result == SUCCESS) && (statf.st_mode & S_IFDIR));
+}
+
+/*********************************************************************
+ * Function:    read_string
+ *
+ * Description: For the given valid file path, reads the data in
+ *              that file.
+ *
+ * Input:   'filepath' the file whose data is to be accessed.
+ *          'lustre_var' the data from the file is read into
+ *           this variable, returned to the requestor.
+ *          'var_max_size' the max size of the string
+ *          'report_error' boolean if error should be reported on 
+ *           missing filepath
+ *
+ * Output:  Returns SUCCESS if read successfully from file else
+ *          returns ERROR.
+ *********************************************************************/
+int  read_string(const char *filepath, char *lustre_var, size_t var_max_size)
+{
+    FILE    *fptr = NULL;
+    int     len = 0;
+    int     ret_val = SUCCESS;
+    int     report_error = 1;
+
+    if ((filepath == NULL) || (lustre_var == NULL)) {
+        report("%s %s:line %d %s", __FILE__, __FUNCTION__, __LINE__,
+               "Input parameter is NULL");
+        ret_val = ERROR;
+    } else {
+        fptr = fopen(filepath, "r");
+
+        if (fptr == NULL) {
+            if(report_error)
+                report("%s %s:line %d Unable to open the file %s", __FILE__,
+                       __FUNCTION__, __LINE__, filepath);
+            ret_val = ERROR;
+        } else {
+            if (fgets(lustre_var, var_max_size, fptr) == NULL) {
+                report("%s %s:line %d read failed for file %s", __FILE__,
+                       __FUNCTION__, __LINE__, filepath);
+                 ret_val = ERROR;
+            } else {
+                len = strlen(lustre_var);
+                /*
+                    Last char is EOF, before string ends,
+                    so '\0' is moved to last but one.
+                */
+                lustre_var[len-1] = lustre_var[len];
+            }
+            fclose(fptr);
+        }
+    }
+    return ret_val;
+}
+
+/**************************************************************************
+ * Function:   lustrefs_ctrl
+ *
+ * Description: Execute /etc/init.d/lustre script for starting,
+ *              stopping and restarting Lustre services in child process.
+ *
+ * Input:  Start/Stop/Restart Command Number.
+ * Output: Returns  void
+ *
+ **************************************************************************/
+
+void lustrefs_ctrl(int command)
+{
+    char *cmd[3];
+
+    cmd[0] = LUSTRE_SERVICE;
+    switch (command) {
+    case ONLINE:
+        cmd[1] = "start";
+        break;
+    case OFFLINE:
+        cmd[1] = "stop";
+        break;
+    case RESTART:
+        cmd[1] = "restart";
+        break;
+    default:
+        return;
+    }
+
+    cmd[2] = (char *)0;
+
+    if (fork() == 0) {
+        execvp(cmd[0], cmd);
+        report("failed to execvp(\'%s %s\')",cmd[0],cmd[1]);
+    }
+    return;
+}
+
+/*****************************************************************************
+ * Function:     get_sysstatus
+ *
+ * Description:  Read /var/lustre/sysStatus file, and based on file contents
+ *               return the status of Lustre services.
+ *
+ * Input:   void
+ * Output:  Return ONLINE/OFFLINE/ONLINE PENDING/OFFLINE PENDING status
+ *          values.
+ *
+ ****************************************************************************/
+
+int get_sysstatus(void)
+{
+    FILE    *fptr = NULL;
+    int     len = 0;
+    int     ret_val = ERROR ;
+    char    sys_status[50] = {0};
+    
+    if(SUCCESS == read_string(FILENAME_SYS_STATUS,sys_status,sizeof(sys_status)))
+    {
+        if (memcmp(sys_status, STR_ONLINE_PENDING,strlen(STR_ONLINE_PENDING)) == 0)
+            ret_val = ONLINE_PENDING;
+        else if (memcmp(sys_status, STR_ONLINE, strlen(STR_ONLINE)) == 0)
+            ret_val = ONLINE;
+        else if (memcmp(sys_status, STR_OFFLINE_PENDING,strlen(STR_OFFLINE_PENDING)) == 0)
+            ret_val = OFFLINE_PENDING;
+        else if (memcmp(sys_status, STR_OFFLINE, strlen(STR_OFFLINE)) == 0)
+            ret_val = OFFLINE;
+        else
+            report("%s %s:line %d Bad Contents in file %s \'%s\'", __FILE__,
+                __FUNCTION__, __LINE__, FILENAME_SYS_STATUS,sys_status);
+    }
+    return ret_val;
+}
+
+
+/*****************************************************************************
+ * Function:     read_ulong
+ *
+ * Description:  Read long values from lproc and copy to the location
+ *               pointed by input parameter.
+ *
+ * Input:   file path, and pointer for data to be copied
+ *
+ * Output:  Return ERROR or SUCCESS.
+ *
+ ****************************************************************************/
+
+int read_ulong(const char *file_path, unsigned long *valuep)
+{
+    char    file_data[MAX_LINE_SIZE];
+    int     ret_val;
+
+    if ((ret_val = read_string(file_path, file_data,sizeof(file_data))) == SUCCESS){
+        *valuep = strtoul(file_data,NULL,10);
+    }
+    return ret_val;
+}
+
+/*****************************************************************************
+ * Function:     read_counter64
+ *
+ * Description:  Read counter64 values from lproc and copy to the location
+ *               pointed by input parameter.
+ *
+ * Input:   file path, and pointer for data to be copied
+ *
+ * Output:  Return ERROR or SUCCESS.
+ *
+ ****************************************************************************/
+
+int read_counter64(const char *file_path, counter64 *c64,int factor)
+{
+    char    file_data[MAX_LINE_SIZE];
+    int     ret_val;
+    unsigned long long tmp = 0;
+
+    if ((ret_val = read_string(file_path, file_data,sizeof(file_data))) == SUCCESS) {
+        tmp = atoll(file_data) * factor;
+        c64->low = (ulong) (0x0FFFFFFFF & tmp);
+        tmp >>= 32; /* Shift right by 4 bytes */
+        c64->high = (ulong) (0x0FFFFFFFF & tmp);
+    }
+    return ret_val;
+}
+
+/*****************************************************************************
+ * Function:     get_nth_entry_from_list
+ *
+ * Description:  Find the n'th entry from a null terminated list of string
+ *
+ * Input:   dir_list - the list
+ *          num - the number of elements in the list
+ *          index - the index we are looking for
+ *
+ * Output:  Return NULL on failure, or the string name on success.
+ *
+ ****************************************************************************/
+
+const char *get_nth_entry_from_list(const char* dir_list,int num,int index)
+{
+    int i;
+    int cur_ptr = 0;
+    for(i=0;i<num;i++){
+        
+        /* 
+         * if we've reached the end of the list for some reason
+         * because num was wrong then stop processing
+         */
+        if( *(dir_list+cur_ptr) == 0)
+            break;
+            
+        /* If we've found the right one */    
+        if( i == index )
+            return dir_list+cur_ptr;
+            
+        /* Move to the next one*/            
+        cur_ptr += strlen(dir_list + cur_ptr)+1;
+    }
+    return NULL;
+}
+
+/*****************************************************************************
+ * Function:    report
+ *
+ * Description: This function used to report error msg to stderr and log into
+ *    log file(default file:/var/log/snmpd.log) when agent is started with
+ *    debug option -Dlsnmpd
+ * Input:   format string and variable arguments.
+ * Output:  void
+ ****************************************************************************/
+
+void report(const char *fmt, ...)
+{
+    char buf[1024];
+
+    va_list arg_list;
+    va_start(arg_list, fmt);
+    vsprintf(buf, fmt, arg_list);
+    va_end(arg_list);
+
+    DEBUGMSGTL(("lsnmpd", "%s\n", buf));
+    fprintf(stderr, "%s\n", buf);
+    return;
+}
+
+
+
+/**************************************************************************
+ * Function:   oid_table_ulong_handler
+ *
+ * Description: Fetch a unsigned long from the given location.
+ *              Setup var_len, and return a pointer to the data.
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* 
+    oid_table_ulong_handler(
+        const char* file_path,
+        size_t  *var_len)
+{
+    static unsigned long ulong_ret;
+    if (SUCCESS != read_ulong(file_path,&ulong_ret))
+        return NULL;
+    *var_len = sizeof(ulong_ret);
+    return  (unsigned char *) &ulong_ret;
+}
+
+/**************************************************************************
+ * Function:   oid_table_c64_handler
+ *
+ * Description: Fetch a counter64 from the given location.
+ *              Setup var_len, and return a pointer to the data.
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* oid_table_c64_handler(const char* file_path,size_t  *var_len)
+{
+    static counter64 c64;
+    if (SUCCESS != read_counter64(file_path,&c64,1))
+        return NULL;
+    *var_len = sizeof(c64);
+    return (unsigned char *) &c64;
+}
+
+/**************************************************************************
+ * Function:   oid_table_c64_kb_handler
+ *
+ * Description: Fetch a counter64 from the given location.
+ *              Setup var_len, and return a pointer to the data.
+ *              Different than oid_table_c64_handler in that
+ *              the original value is multiplied by 1024 before converting
+ *              to a counter64.  (e.g. turn KB into a Byte scaled value)
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* oid_table_c64_kb_handler(const char* file_path,size_t  *var_len)
+{
+    static counter64 c64;
+    /* scale by factor of 1024*/
+    if (SUCCESS != read_counter64(file_path,&c64,1024))
+        return NULL;
+    *var_len = sizeof(c64);
+    return (unsigned char *) &c64;
+}
+
+/**************************************************************************
+ * Function:   oid_table_obj_name_handler
+ *
+ * Description: Just copy the file_path and return as the output value.
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* 
+    oid_table_obj_name_handler(
+        const char* file_path,
+        size_t  *var_len)
+{
+    static unsigned char string[SPRINT_MAX_LEN];
+    *var_len = strlen(file_path);
+    *var_len = MIN_LEN(*var_len, sizeof(string));
+    memcpy(string, file_path, *var_len);
+    return (unsigned char *) string;
+}
+
+/**************************************************************************
+ * Function:   oid_table_string_handler
+ *
+ * Description: Fetch a string from the given location.
+ *              Setup var_len, and return a pointer to the data.
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* 
+    oid_table_string_handler(
+        const char* file_path,
+        size_t  *var_len)
+{
+    static unsigned char string[SPRINT_MAX_LEN];
+    if( SUCCESS != read_string(file_path, string,sizeof(string)))
+        return NULL;
+    *var_len = strlen(string);
+    return (unsigned char *) string;
+}
+
+
+/**************************************************************************
+ * Function:   oid_table_is_directory_handler
+ *
+ * Description: Determine if the file_path is a directory.  
+ *              Setup a boolean return value.
+ *              Setup var_len, and return a pointer to the data.
+ *
+ * Input:  file_path, and var_len pointer
+ *
+ * Output: NULL on failure, or pointer to data
+ *
+ **************************************************************************/
+
+unsigned char* 
+    oid_table_is_directory_handler(
+        const char* file_path,
+        size_t *var_len)
+{
+    static long long_ret;
+    long_ret =  is_directory(file_path);
+    *var_len = sizeof(long_ret);
+    return (unsigned char *) &long_ret;
+}
+
+/**************************************************************************
+ * Function:   var_genericTable
+ *
+ * Description: Handle Table driven OID processing
+ *
+ **************************************************************************/
+
+unsigned char *
+var_genericTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method,
+            const char *path,
+            struct oid_table *ptable)
+{
+    char *dir_list;
+    uint32_t num;
+    int  deviceindex;
+    unsigned char *ret_val = NULL;
+    int i=0;
+    const char* obj_name;
+    
+    
+    /*
+     * Get the list of file.  If there are no elements
+     * return nothing
+     */
+    if( 0 == (dir_list = get_file_list(path, DIR_TYPE, &num)))
+        return NULL;
+
+    /*
+     * Setup the table
+     */
+    if (header_simple_table(vp,name,length,exact,var_len,write_method, num)
+                                                == MATCH_FAILED )
+        goto cleanup_and_exit;
+
+    /*
+     * The number of the device we're looking at
+     */
+    deviceindex = name[*length - 1] - 1;
+
+    /*
+     * If we couldn't find this element
+     * something must have recently changed return
+     * nothing
+     */
+    if(deviceindex >= num){
+        report("deviceindex=%d exceeds number of elements=%d",deviceindex,num);
+        goto cleanup_and_exit;
+    }
+
+    /*
+     * Fetch the object name from the list
+     */
+    obj_name = get_nth_entry_from_list(dir_list,num,deviceindex);
+    if(obj_name == NULL){
+        /*
+         * Note this should never really happen because we check deviceindex >=num
+         * above.  And dir_list should be consitent with num
+         * but just in case...
+         */
+        report("object name not found in list",deviceindex,num);
+        goto cleanup_and_exit;
+    }
+
+    /*
+     * Find the matching magic - or the end of the list
+     */
+    while(ptable[i].magic != vp->magic && ptable[i].magic != 0)
+        i++;
+
+    /*
+     * If we didn't find a matching entry return
+     */
+    if(ptable[i].magic==0)
+        goto cleanup_and_exit;
+
+    /*
+     * If the name is NULL is a special case and 
+     * just just pass the obj_name as the file_path
+     * otherwise we create a file path from the given components
+     */
+    if(ptable[i].name != 0){
+        char file_path[MAX_PATH_SIZE];
+        sprintf(file_path, "%s%s/%s",path,obj_name,ptable[i].name);
+        ret_val =  ptable[i].fhandler(file_path,var_len);
+    }
+    else
+        ret_val =  ptable[i].fhandler(obj_name,var_len);
+
+cleanup_and_exit:
+    free(dir_list);
+    return ret_val;
+};
+
diff --git a/snmp/lustre-snmp-util.h b/snmp/lustre-snmp-util.h
new file mode 100644 (file)
index 0000000..087e8cc
--- /dev/null
@@ -0,0 +1,197 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LUSTRE_SNMP_UTIL_H
+#define LUSTRE_SNMP_UTIL_H
+
+/*
+ * Definitions of magic values
+ */
+
+#define SYSVERSION          20
+#define SYSKERNELVERSION    21
+#define SYSHEALTHCHECK      22
+#define SYSSTATUS           23
+
+#define OSDNUMBER           30
+#define OSDUUID             31
+#define OSDCOMMONNAME       32
+#define OSDCAPACITY         33
+#define OSDFREECAPACITY     34
+#define OSDOBJECTS          35
+#define OSDFREEOBJECTS      36
+
+#define OSCNUMBER           40
+#define OSCUUID             41
+#define OSCCOMMONNAME       42
+#define OSCOSTSERVERUUID    43
+#define OSCCAPACITY         44
+#define OSCFREECAPACITY     45
+#define OSCOBJECTS          46
+#define OSCFREEOBJECTS      47
+
+#define MDDNUMBER           50
+#define MDDUUID             51
+#define MDDCOMMONNAME       52
+#define MDDCAPACITY         53
+#define MDDFREECAPACITY     54
+#define MDDFILES            55
+#define MDDFREEFILES        56
+
+#define MDCNUMBER           60
+#define MDCUUID             61
+#define MDCCOMMONNAME       62
+#define MDCMDSSERVERUUID    63
+#define MDCCAPACITY         64
+#define MDCFREECAPACITY     65
+#define MDCOBJECTS          66
+#define MDCFREEOBJECTS      67
+
+#define CLIMOUNTNUMBER      70
+#define CLIUUID             71
+#define CLICOMMONNAME       72
+#define CLIMDCUUID          73
+#define CLIMDCCOMMONNAME    74
+#define CLIUSESLOV          75
+#define CLILOVUUID          76
+#define CLILOVCOMMONNAME    77
+
+#define LOVNUMBER           80
+#define LOVUUID             81
+#define LOVCOMMONNAME       82
+#define LOVNUMOBD           83
+#define LOVNUMACTIVEOBD     84
+#define LOVCAPACITY         85
+#define LOVFREECAPACITY     86
+#define LOVFILES            87
+#define LOVFREEFILES        88
+#define LOVSTRIPECOUNT      89
+#define LOVSTRIPEOFFSET     90
+#define LOVSTRIPESIZE       91
+#define LOVSTRIPETYPE       92
+
+#define LDLMNUMBER          100
+#define LDLMNAMESPACE       101
+#define LDLMLOCKCOUNT       102
+#define LDLMUNUSEDLOCKCOUNT 103
+#define LDLMRESOURCECOUNT   104
+
+/* Defining the proc paths for Lustre file system */
+#define LUSTRE_PATH                 "/proc/fs/lustre/"
+#define OSD_PATH                    LUSTRE_PATH "obdfilter/"
+#define OSC_PATH                    LUSTRE_PATH "osc/"
+#define MDS_PATH                    LUSTRE_PATH "mds/"
+#define MDC_PATH                    LUSTRE_PATH "mdc/"
+#define CLIENT_PATH                 LUSTRE_PATH "llite/"
+#define LOV_PATH                    LUSTRE_PATH "lov/"
+#define LDLM_PATH                   LUSTRE_PATH "ldlm/namespaces/"
+
+/* Common procfs file entries that are refrenced in mulitple locations*/
+#define FILENAME_SYSHEALTHCHECK     "health_check"
+#define FILENAME_SYS_STATUS         "/var/lustre/sysStatus"
+
+#define FILENAME_NUM_REF            "num_refs"
+#define FILENAME_UUID               "uuid"
+#define FILENAME_COMMON_NAME        "common_name"
+#define FILENAME_KBYTES_TOTAL       "kbytestotal"
+#define FILENAME_KBYTES_FREE        "kbytesfree"
+#define FILENAME_FILES_TOTAL        "filestotal"
+#define FILENAME_FILES_FREE         "filesfree"
+
+/* strings which the file /var/lustre/sysStatus can hold */
+#define STR_ONLINE                  "online"
+#define STR_ONLINE_PENDING          "online pending"
+#define STR_OFFLINE                 "offline"
+#define STR_OFFLINE_PENDING         "offline pending"
+
+
+/* Script required for starting/stopping lustre services */
+#define LUSTRE_SERVICE              "/etc/init.d/lustre"
+
+#define MIN_LEN(val1,val2)          (((val1)>(val2))?(val2):(val1))
+
+/* The max size of a lustre procfs path name*/
+#define MAX_PATH_SIZE               512
+
+/* The max size of a string read from procfs */
+#define MAX_LINE_SIZE               512
+
+/* Types passed to get_file_list() */
+#define DIR_TYPE                    1
+#define FILE_TYPE                   0
+
+/* Defining return values */
+#define SUCCESS                     0
+#define ERROR                       -1
+
+typedef struct counter64 counter64;
+
+typedef enum {
+    ONLINE = 1,
+    OFFLINE,
+    ONLINE_PENDING,
+    OFFLINE_PENDING,
+    RESTART
+} lustre_sysstatus;
+
+/* File operation related functions */
+char *get_file_list(const char *dirname, int file_type, uint32_t *count);
+extern int  is_directory(const char *filename);
+extern int  read_string(const char *filepath, char *lustre_var,size_t var_size);
+int read_counter64(const char *file_path, counter64 *c64,int factor);
+int read_ulong(const char *file_path,unsigned long* valuep);
+
+/* Start/Stop/Restart Lustre Services */
+extern void lustrefs_ctrl(int command);
+extern int get_sysstatus();
+
+extern void report(const char *fmt, ...);
+
+/* Table Driven SNMP OID Handler support*/
+typedef unsigned char* (*f_oid_handler_t)(
+    const char* file_path,
+    size_t  *var_len);
+
+struct oid_table
+{
+    int magic;                  /*The magic number*/ 
+    const char *name;           /*The procfs name*/
+    f_oid_handler_t fhandler;   /*The handler */
+};
+
+unsigned char* oid_table_ulong_handler(const char* file_path,size_t  *var_len);
+unsigned char* oid_table_c64_handler(const char* file_path,size_t  *var_len);
+unsigned char* oid_table_c64_kb_handler(const char* file_path,size_t  *var_len);
+unsigned char* oid_table_obj_name_handler(const char* file_path,size_t  *var_len);
+unsigned char* oid_table_string_handler(const char* file_path,size_t *var_len);
+unsigned char* oid_table_is_directory_handler(const char* file_path,size_t *var_len);
+unsigned char *
+    var_genericTable(struct variable *vp,
+        oid     *name,
+        size_t  *length,
+        int     exact,
+        size_t  *var_len,
+        WriteMethod **write_method,
+        const char *path,
+        struct oid_table *ptable);
+
+#endif /* LUSTRE_SNMP_UTIL_H */
diff --git a/snmp/lustre-snmp.c b/snmp/lustre-snmp.c
new file mode 100644 (file)
index 0000000..0de2c4d
--- /dev/null
@@ -0,0 +1,601 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/utilities.h>
+#include <pthread.h>
+#include "lustre-snmp.h"
+
+/* 
+ * clusterFileSystems_variables_oid:
+ *   this is the top level oid that we want to register under.  This
+ *   is essentially a prefix, with the suffix appearing in the
+ *   variable below.
+ */
+
+
+oid clusterFileSystems_variables_oid[] = { 1,3,6,1,4,1,13140 };
+
+
+/* 
+ * variable7 clusterFileSystems_variables:
+ *   this variable defines function callbacks and type return information 
+ *   for the clusterFileSystems mib section 
+ */
+
+
+struct variable7 clusterFileSystems_variables[] = {
+/*  magic number        , variable type , ro/rw , callback fn  , L, oidsuffix */
+
+  /* sytemInformation 2.1.1. */
+  { SYSVERSION          , ASN_OCTET_STR , RONLY , var_clusterFileSystems, 4, { 2,1,1,1 } },
+  { SYSKERNELVERSION    , ASN_OCTET_STR , RONLY , var_clusterFileSystems, 4, { 2,1,1,2 } },
+  { SYSHEALTHCHECK      , ASN_OCTET_STR , RONLY , var_clusterFileSystems, 4, { 2,1,1,3 } },
+  { SYSSTATUS           , ASN_INTEGER   , RWRITE, var_clusterFileSystems, 4, { 2,1,1,4 } },
+
+  /* objectStorageTargets 2.1.2 */
+  { OSDNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,2,1 } },
+
+  /* objectStorageTargets.osdTable.osdEntry 2.1.2.2.1 */
+  { OSDUUID             , ASN_OCTET_STR , RONLY , var_osdTable, 6, { 2,1,2,2,1,2 } },
+  { OSDCOMMONNAME       , ASN_OCTET_STR , RONLY , var_osdTable, 6, { 2,1,2,2,1,3 } },
+  { OSDCAPACITY         , ASN_COUNTER64 , RONLY , var_osdTable, 6, { 2,1,2,2,1,4 } },
+  { OSDFREECAPACITY     , ASN_COUNTER64 , RONLY , var_osdTable, 6, { 2,1,2,2,1,5 } },
+  { OSDOBJECTS          , ASN_COUNTER64 , RONLY , var_osdTable, 6, { 2,1,2,2,1,6 } },
+  { OSDFREEOBJECTS      , ASN_COUNTER64 , RONLY , var_osdTable, 6, { 2,1,2,2,1,7 } },
+
+  /* objectStorageClients 2.1.3 */
+  { OSCNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,3,1 } },
+
+  /* objectStorageClients.oscTable.oscEntry 2.1.3.2.1 */
+  { OSCUUID             , ASN_OCTET_STR , RONLY , var_oscTable, 6, { 2,1,3,2,1,2 } },
+  { OSCCOMMONNAME       , ASN_OCTET_STR , RONLY , var_oscTable, 6, { 2,1,3,2,1,3 } },
+  { OSCOSTSERVERUUID    , ASN_OCTET_STR , RONLY , var_oscTable, 6, { 2,1,3,2,1,4 } },
+  { OSCCAPACITY         , ASN_COUNTER64 , RONLY , var_oscTable, 6, { 2,1,3,2,1,5 } },
+  { OSCFREECAPACITY     , ASN_COUNTER64 , RONLY , var_oscTable, 6, { 2,1,3,2,1,6 } },
+  { OSCOBJECTS          , ASN_COUNTER64 , RONLY , var_oscTable, 6, { 2,1,3,2,1,7 } },
+  { OSCFREEOBJECTS      , ASN_COUNTER64 , RONLY , var_oscTable, 6, { 2,1,3,2,1,8 } },
+
+
+  /* metaDataServers 2.1.4 */
+  { MDDNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,4,1 } },
+
+  /* metaDataServers.mddTable.mddEntry 2.1.4.2.1 */
+  { MDDUUID             , ASN_OCTET_STR , RONLY , var_mdsTable, 6, { 2,1,4,2,1,2 } },
+  { MDDCOMMONNAME       , ASN_OCTET_STR , RONLY , var_mdsTable, 6, { 2,1,4,2,1,3 } },
+  { MDDCAPACITY         , ASN_COUNTER64 , RONLY , var_mdsTable, 6, { 2,1,4,2,1,4 } },
+  { MDDFREECAPACITY     , ASN_COUNTER64 , RONLY , var_mdsTable, 6, { 2,1,4,2,1,5 } },
+  { MDDFILES            , ASN_COUNTER64 , RONLY , var_mdsTable, 6, { 2,1,4,2,1,6 } },
+  { MDDFREEFILES        , ASN_COUNTER64 , RONLY , var_mdsTable, 6, { 2,1,4,2,1,7 } },
+
+  /* metaDataClients 2.1.5 */
+  { MDCNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,5,1 } },
+
+  /* metaDataClients.mdcTable.mdcEntry 2.1.5.2.1 */
+  { MDCUUID             , ASN_OCTET_STR , RONLY , var_mdcTable, 6, { 2,1,5,2,1,2 } },
+  { MDCCOMMONNAME       , ASN_OCTET_STR , RONLY , var_mdcTable, 6, { 2,1,5,2,1,3 } },
+  { MDCMDSSERVERUUID    , ASN_OCTET_STR , RONLY , var_mdcTable, 6, { 2,1,5,2,1,4 } },
+  { MDCCAPACITY         , ASN_COUNTER64 , RONLY , var_mdcTable, 6, { 2,1,5,2,1,5 } },
+  { MDCFREECAPACITY     , ASN_COUNTER64 , RONLY , var_mdcTable, 6, { 2,1,5,2,1,6 } },
+  { MDCOBJECTS          , ASN_COUNTER64 , RONLY , var_mdcTable, 6, { 2,1,5,2,1,7 } },
+  { MDCFREEOBJECTS      , ASN_COUNTER64 , RONLY , var_mdcTable, 6, { 2,1,5,2,1,8 } },
+
+  /* lustreClients 2.1.6 */
+  { CLIMOUNTNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,6,1 } },
+
+  /* lustreClients.cliMountTable.cliMountEntry 2.1.6.2.1 */
+  { CLIUUID             , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,2 } },
+  { CLICOMMONNAME       , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,3 } },
+  { CLIMDCUUID          , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,4 } },
+  { CLIMDCCOMMONNAME    , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,5 } },
+  { CLIUSESLOV          , ASN_INTEGER ,   RONLY , var_cliTable, 6, { 2,1,6,2,1,6 } },
+  { CLILOVUUID          , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,7 } },
+  { CLILOVCOMMONNAME    , ASN_OCTET_STR , RONLY , var_cliTable, 6, { 2,1,6,2,1,8 } },
+
+  /* logicalObjectVolume 2.1.7 */
+  { LOVNUMBER           , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,7,1 } },
+
+  /* logicalObjectVolume.osdTable.lovTable 2.1.2.2.1 */
+  { LOVUUID             , ASN_OCTET_STR , RONLY , var_lovTable, 6, { 2,1,7,2,1,2 } },
+  { LOVCOMMONNAME       , ASN_OCTET_STR , RONLY , var_lovTable, 6, { 2,1,7,2,1,3 } },
+  { LOVNUMOBD           , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,4 } },
+  { LOVNUMACTIVEOBD     , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,5 } },
+  { LOVCAPACITY         , ASN_COUNTER64 , RONLY , var_lovTable, 6, { 2,1,7,2,1,6 } },
+  { LOVFREECAPACITY     , ASN_COUNTER64 , RONLY , var_lovTable, 6, { 2,1,7,2,1,7 } },
+  { LOVFILES            , ASN_COUNTER64 , RONLY , var_lovTable, 6, { 2,1,7,2,1,8 } },
+  { LOVFREEFILES        , ASN_COUNTER64 , RONLY , var_lovTable, 6, { 2,1,7,2,1,9 } },
+  { LOVSTRIPECOUNT      , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,10} },
+  { LOVSTRIPEOFFSET     , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,11} },
+  { LOVSTRIPESIZE       , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,12} },
+  { LOVSTRIPETYPE       , ASN_UNSIGNED ,  RONLY , var_lovTable, 6, { 2,1,7,2,1,13} },
+
+  /* lustreLDLM 2.1.8 */
+  { LDLMNUMBER          , ASN_UNSIGNED  , RONLY , var_clusterFileSystems, 4, { 2,1,8,1 } },
+
+  /* lustreLDLM.ldlmTable.ldlmEntry 2.1.8.2.1 */
+  { LDLMNAMESPACE       , ASN_OCTET_STR , RONLY , var_ldlmTable, 6, { 2,1,8,2,1,2 } },
+  { LDLMLOCKCOUNT       , ASN_UNSIGNED  , RONLY , var_ldlmTable, 6, { 2,1,8,2,1,3 } },
+  { LDLMUNUSEDLOCKCOUNT , ASN_UNSIGNED  , RONLY , var_ldlmTable, 6, { 2,1,8,2,1,4 } },
+  { LDLMRESOURCECOUNT   , ASN_UNSIGNED  , RONLY , var_ldlmTable, 6, { 2,1,8,2,1,5 } },
+
+};
+
+/*****************************************************************************
+ * Function: init_cfsNetSNMPPlugin
+ *
+ * Description: Called when the agent starts up
+ *
+ * Input:   void
+ *
+ * Output:  None
+ *
+ ****************************************************************************/
+void init_lustresnmp(void) {
+
+  /* register ourselves with the agent to handle our mib tree */
+  REGISTER_MIB("clusterFileSystems", clusterFileSystems_variables, variable7,
+               clusterFileSystems_variables_oid);
+               
+   initilize_trap_handler();
+
+  DEBUGMSGTL(("lsnmpd", "%s %s \n", __FUNCTION__, "Initialization Done"));
+}
+
+/*****************************************************************************
+ * Function: deinit_cfsNetSNMPPlugin
+ *
+ * Description: Called when the agent terminates up
+ *
+ * Input:   void
+ *
+ * Output:  None
+ *
+ ****************************************************************************/
+
+void deinit_lustresnmp(void) {
+
+  /* deregister ourselves with the agent */
+  unregister_mib(clusterFileSystems_variables_oid,
+    sizeof(clusterFileSystems_variables_oid)/sizeof(clusterFileSystems_variables_oid));
+  
+  terminate_trap_handler();
+  
+  DEBUGMSGTL(("lsnmpd", "%s %s \n", __FUNCTION__, "Termination Done"));
+}
+
+/*****************************************************************************
+ * Function: var_clusterFileSystems
+ *
+ ****************************************************************************/
+unsigned char *
+var_clusterFileSystems(struct variable *vp, 
+                oid     *name, 
+                size_t  *length, 
+                int     exact, 
+                size_t  *var_len, 
+                WriteMethod **write_method)
+{
+
+
+  /* variables we may use later */
+  static long long_ret;
+  static u_long ulong_ret;
+  static unsigned char string[SPRINT_MAX_LEN];
+  char file_path[MAX_PATH_SIZE];
+  uint32_t num;
+  char *dir_list;
+
+  if (header_generic(vp,name,length,exact,var_len,write_method)
+                                  == MATCH_FAILED )
+    return NULL;
+
+
+  /* 
+   * this is where we do the value assignments for the mib results.
+   */
+  switch(vp->magic) {
+
+    case SYSVERSION:
+        sprintf(file_path, "%s%s", LUSTRE_PATH,"version");
+        if( SUCCESS != read_string(file_path, string,sizeof(string)))
+            return NULL;
+        *var_len = strlen(string);
+        return (unsigned char *) string;
+
+    case SYSKERNELVERSION:
+        sprintf(file_path, "%s%s", LUSTRE_PATH,"kernel_version");
+        if( SUCCESS != read_string(file_path, string,sizeof(string)))
+            return NULL;
+        *var_len = strlen(string);
+        return (unsigned char *) string;
+
+    case SYSHEALTHCHECK:
+        sprintf(file_path, "%s%s", LUSTRE_PATH,FILENAME_SYSHEALTHCHECK);
+        if( SUCCESS != read_string(file_path, string,sizeof(string)))
+            return NULL;
+        *var_len = strlen(string);
+        return (unsigned char *) string;
+
+    case SYSSTATUS:
+        *write_method = write_sysStatus;
+        long_ret = (long) get_sysstatus();
+        if (long_ret != ERROR)
+          return (unsigned char *) &long_ret;
+        return NULL;
+                      
+    case OSDNUMBER:
+        if( 0 == (dir_list = get_file_list(OSD_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",OSD_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case OSCNUMBER:
+        if( 0 == (dir_list = get_file_list(OSC_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",OSC_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case MDDNUMBER:
+        if( 0 == (dir_list = get_file_list(MDS_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",MDS_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case MDCNUMBER:
+        if( 0 == (dir_list = get_file_list(MDC_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",MDC_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case CLIMOUNTNUMBER:
+        if( 0 == (dir_list = get_file_list(CLIENT_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",CLIENT_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case LOVNUMBER:
+        if( 0 == (dir_list = get_file_list(LOV_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",LOV_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    case LDLMNUMBER:
+        if( 0 == (dir_list = get_file_list(LDLM_PATH, DIR_TYPE, &num)))
+            return NULL;
+        DEBUGMSGTL(("lsnmpd","num(%s)=%d\n",LDLM_PATH,num));  
+        ulong_ret =  num;
+        free(dir_list);
+        return (unsigned char *) &ulong_ret;
+
+    default:
+      ERROR_MSG("");
+  }
+  return NULL;
+}
+
+struct oid_table osd_table[] =
+{ 
+    { OSDUUID,FILENAME_UUID,oid_table_string_handler},
+    { OSDCOMMONNAME,0,oid_table_obj_name_handler},
+    { OSDCAPACITY,FILENAME_KBYTES_TOTAL, oid_table_c64_kb_handler},
+    { OSDFREECAPACITY,FILENAME_KBYTES_FREE, oid_table_c64_kb_handler},
+    { OSDOBJECTS,FILENAME_FILES_TOTAL, oid_table_c64_kb_handler},
+    { OSDFREEOBJECTS,FILENAME_FILES_FREE, oid_table_c64_kb_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+
+/*****************************************************************************
+ * Function: var_osdTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_osdTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        OSD_PATH,osd_table);
+}
+
+struct oid_table osc_table[] =
+{ 
+    { OSCUUID,FILENAME_UUID,oid_table_string_handler},
+    { OSCCOMMONNAME,0,oid_table_obj_name_handler},
+    { OSCOSTSERVERUUID,"ost_server_uuid",oid_table_string_handler},
+    { OSCCAPACITY,FILENAME_KBYTES_TOTAL, oid_table_c64_kb_handler},
+    { OSCFREECAPACITY,FILENAME_KBYTES_FREE, oid_table_c64_kb_handler},
+    { OSCOBJECTS,FILENAME_FILES_TOTAL, oid_table_c64_kb_handler},
+    { OSCFREEOBJECTS,FILENAME_FILES_FREE, oid_table_c64_kb_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+/*****************************************************************************
+ * Function: var_oscTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_oscTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        OSC_PATH,osc_table);
+}
+
+struct oid_table mds_table[] =
+{ 
+    { MDDUUID,FILENAME_UUID,oid_table_string_handler},
+    { MDDCOMMONNAME,0,oid_table_obj_name_handler},
+    { MDDCAPACITY,FILENAME_KBYTES_TOTAL, oid_table_c64_kb_handler},
+    { MDDFREECAPACITY,FILENAME_KBYTES_FREE, oid_table_c64_kb_handler},
+    { MDDFILES,FILENAME_FILES_TOTAL, oid_table_c64_kb_handler},
+    { MDDFREEFILES,FILENAME_FILES_FREE, oid_table_c64_kb_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+/*****************************************************************************
+ * Function: var_mdsTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_mdsTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        MDS_PATH,mds_table);
+}
+
+struct oid_table mdc_table[] =
+{ 
+    { MDCUUID,FILENAME_UUID,oid_table_string_handler},
+    { MDCCOMMONNAME,0,oid_table_obj_name_handler},
+    { MDCMDSSERVERUUID,"mds_server_uuid",oid_table_string_handler},
+    { MDCCAPACITY,FILENAME_KBYTES_TOTAL, oid_table_c64_kb_handler},
+    { MDCFREECAPACITY,FILENAME_KBYTES_FREE, oid_table_c64_kb_handler},
+    { MDCOBJECTS,FILENAME_FILES_TOTAL, oid_table_c64_kb_handler},
+    { MDCFREEOBJECTS,FILENAME_FILES_FREE, oid_table_c64_kb_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+
+/*****************************************************************************
+ * Function: var_mdcTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_mdcTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        MDC_PATH,mdc_table);
+}
+
+
+struct oid_table cli_table[] =
+{ 
+    { CLIUUID,FILENAME_UUID,oid_table_string_handler},
+    { CLICOMMONNAME,0,oid_table_obj_name_handler},
+    { CLIMDCUUID,"mdc/" FILENAME_UUID,oid_table_string_handler},
+    { CLIMDCCOMMONNAME,"mdc/" FILENAME_COMMON_NAME,oid_table_string_handler},
+    { CLIUSESLOV,"lov/",oid_table_is_directory_handler},
+    { CLILOVUUID,"lov/" FILENAME_UUID,oid_table_string_handler},
+    { CLILOVCOMMONNAME,"lov/" FILENAME_COMMON_NAME,oid_table_string_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+/*****************************************************************************
+ * Function: var_cliTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_cliTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        CLIENT_PATH,cli_table);
+}
+
+
+struct oid_table lov_table[] =
+{ 
+    { LOVUUID,FILENAME_UUID,oid_table_string_handler},
+    { LOVCOMMONNAME,0,oid_table_obj_name_handler},
+    { LOVNUMOBD,"numobd", oid_table_ulong_handler},
+    { LOVNUMACTIVEOBD,"activeobd", oid_table_ulong_handler},
+    { LOVCAPACITY,FILENAME_KBYTES_TOTAL, oid_table_c64_kb_handler},
+    { LOVFREECAPACITY,FILENAME_KBYTES_FREE, oid_table_c64_kb_handler},
+    { LOVFILES,FILENAME_FILES_TOTAL, oid_table_c64_kb_handler},
+    { LOVFREEFILES,FILENAME_FILES_FREE, oid_table_c64_kb_handler},
+    { LOVSTRIPECOUNT,"stripecount", oid_table_ulong_handler},
+    { LOVSTRIPEOFFSET,"stripeoffset", oid_table_ulong_handler},
+    { LOVSTRIPESIZE,"stripesize", oid_table_ulong_handler},
+    { LOVSTRIPETYPE,"stripetype", oid_table_ulong_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+
+/*****************************************************************************
+ * Function: var_lovTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_lovTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        LOV_PATH,lov_table);
+}
+
+struct oid_table ldlm_table[] =
+{ 
+    { LDLMNAMESPACE,0,oid_table_obj_name_handler},
+    { LDLMLOCKCOUNT,"lock_count", oid_table_ulong_handler},
+    { LDLMUNUSEDLOCKCOUNT,"lock_unused_count", oid_table_ulong_handler},
+    { LDLMRESOURCECOUNT,"resource_count", oid_table_ulong_handler},
+    { 0,0,0 } /*End of table*/
+};
+
+
+/*****************************************************************************
+ * Function: var_ldlmTable
+ *
+ ****************************************************************************/
+unsigned char *
+var_ldlmTable(struct variable *vp,
+           oid     *name,
+           size_t  *length,
+           int     exact,
+           size_t  *var_len,
+           WriteMethod **write_method)
+{
+    return var_genericTable(vp,name,length,exact,var_len,write_method,
+        LDLM_PATH,ldlm_table);
+}
+
+
+/*****************************************************************************
+ * Function: write_sysStatus
+ *
+ ****************************************************************************/
+int
+write_sysStatus(int      action,
+            u_char   *var_val,
+            u_char   var_val_type,
+            size_t   var_val_len,
+            u_char   *statP,
+            oid      *name,
+            size_t   name_len)
+{
+  static long *long_ret;
+  int size;
+  int pid, new_value;
+
+
+
+  switch ( action ) {
+        case RESERVE1:
+          if (var_val_type != ASN_INTEGER){
+              fprintf(stderr, "write to sysStatus not ASN_INTEGER\n");
+              return SNMP_ERR_WRONGTYPE;
+          }
+          if (var_val_len > sizeof(long_ret)){
+              fprintf(stderr,"write to sysStatus: bad length\n");
+              return SNMP_ERR_WRONGLENGTH;
+          }
+          if ((*var_val != ONLINE) &&
+              (*var_val !=  OFFLINE) &&
+              (*var_val !=  RESTART)){
+              report("%s %s:line %d %s", __FILE__, __FUNCTION__, __LINE__,
+                     "sysStatus value is invalid.");
+              return SNMP_ERR_WRONGVALUE;
+          }
+          break;
+
+
+        case RESERVE2:
+          size = var_val_len;
+          long_ret = (long *) var_val;
+
+
+          break;
+
+
+        case FREE:
+             /* Release any resources that have been allocated */
+          break;
+
+
+        case ACTION:
+             /* The variable has been stored in long_ret for
+             you to use, and you have just been asked to do something with
+             it.  Note that anything done here must be reversable in the UNDO case */
+          new_value = *(int *) var_val;
+          switch (new_value) {
+            case ONLINE:
+                lustrefs_ctrl(ONLINE);
+                break;
+
+            case OFFLINE:
+                lustrefs_ctrl(OFFLINE);
+                break;
+
+            case RESTART:
+                lustrefs_ctrl(RESTART);
+                break;
+
+            default:
+                break;
+          }
+          break;
+
+
+        case UNDO:
+             /* Back out any changes made in the ACTION case */
+          break;
+
+
+        case COMMIT:
+             /* Things are working well, so it's now safe to make the change
+             permanently.  Make sure that anything done here can't fail! */
+          break;
+  }
+  return SNMP_ERR_NOERROR;
+}
+
diff --git a/snmp/lustre-snmp.h b/snmp/lustre-snmp.h
new file mode 100644 (file)
index 0000000..c4c10e0
--- /dev/null
@@ -0,0 +1,45 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2005 Cluster File Systems, Inc.
+ *   Author: PJ Kirner <pjkirner@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LUSTRE_SNMP_H
+#define LUSTRE_SNMP_H
+
+#include "lustre-snmp-util.h"
+
+config_require(util_funcs)
+config_add_mib(LUSTRE-MIB)
+config_require(lustre/cfs_util)
+config_require(lustre/cfs_trap)
+
+/* function prototypes */
+void   init_cfsNetSNMPPlugin(void);
+FindVarMethod var_clusterFileSystems;
+FindVarMethod var_osdTable;
+FindVarMethod var_oscTable;
+FindVarMethod var_mdsTable;
+FindVarMethod var_mdcTable;
+FindVarMethod var_cliTable;
+FindVarMethod var_ldlmTable;
+FindVarMethod var_lovTable;
+WriteMethod write_sysStatus;
+
+#endif /* LUSTRE_SNMP_H */