SMARTParser.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:8k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.contrib.failmon;
  19. import java.net.InetAddress;
  20. import java.util.ArrayList;
  21. import java.util.Calendar;
  22. import java.util.regex.Matcher;
  23. import java.util.regex.Pattern;
  24. /**********************************************************
  25.  * Objects of this class parse the output of smartmontools to 
  26.  * gather information about the state of disks in the system. The
  27.  * smartmontools utility reads the S.M.A.R.T. attributes from
  28.  * the disk devices and reports them to the user. Note that since
  29.  * running smartctl requires superuser provileges, one should  
  30.  * grand sudo privileges to the running user for the command smartctl
  31.  * (without a password). Alternatively, one can set up a cron  job that 
  32.  * periodically dumps the output of smartctl into a user-readable file.
  33.  * See the configuration file for details.
  34.  *
  35.  **********************************************************/
  36. public class SMARTParser extends ShellParser {
  37.   String[] devices;
  38.   /**
  39.    * Constructs a SMARTParser and reads the list of disk 
  40.    * devices to query
  41.    */
  42.   public SMARTParser() {
  43.     super();
  44.     String devicesStr = Environment.getProperty("disks.list");
  45.     System.out.println("skato " + devicesStr);
  46.     if (devicesStr != null)
  47.       devices = devicesStr.split(",\s*");
  48.   }
  49.   /**
  50.    * Reads and parses the output of smartctl for a specified disk and 
  51.    * creates an appropriate EventRecord that holds the desirable 
  52.    * information for it. Since the output of smartctl is different for 
  53.    * different kinds of disks, we try to identify as many attributes as 
  54.    * posssible for all known output formats. 
  55.    * 
  56.    * @param device the disk device name to query
  57.    * 
  58.    * @return the EventRecord created
  59.    */
  60.   public EventRecord query(String device) throws Exception {
  61.     String conf = Environment.getProperty("disks." + device + ".source");
  62.     StringBuffer sb;
  63.     if (conf == null)
  64.       sb = Environment.runCommand("sudo smartctl --all " + device);
  65.     else
  66.       sb = Environment.runCommand("cat " + conf);
  67.     EventRecord retval = new EventRecord(InetAddress.getLocalHost()
  68.         .getCanonicalHostName(), InetAddress.getAllByName(InetAddress.getLocalHost()
  69.         .getHostName()), Calendar.getInstance(), "SMART", "Unknown",
  70.         (conf == null ? "sudo smartctl --all " + device : "file " + conf), "-");
  71.     // IBM SCSI disks
  72.     retval.set("model", findPattern("Device\s*:\s*(.*)", sb.toString(), 1));
  73.     retval.set("serial", findPattern("Serial\s+Number\s*:\s*(.*)", sb
  74.         .toString(), 1));
  75.     retval.set("firmware", findPattern("Firmware\s+Version\s*:\s*(.*)", sb
  76.         .toString(), 1));
  77.     retval.set("capacity", findPattern("User\s+Capacity\s*:\s*(.*)", sb
  78.         .toString(), 1));
  79.     retval.set("status", findPattern("SMART\s*Health\s*Status:\s*(.*)", sb
  80.         .toString(), 1));
  81.     retval.set("current_temperature", findPattern(
  82.         "Current\s+Drive\s+Temperature\s*:\s*(.*)", sb.toString(), 1));
  83.     retval.set("trip_temperature", findPattern(
  84.         "Drive\s+Trip\s+Temperature\s*:\s*(.*)", sb.toString(), 1));
  85.     retval.set("start_stop_count", findPattern(
  86.         "start\s+stop\s+count\s*:\s*(\d*)", sb.toString(), 1));
  87.     String[] var = { "read", "write", "verify" };
  88.     for (String s : var) {
  89.       retval.set(s + "_ecc_fast", findPattern(s + "\s*:\s*(\d*)", sb
  90.           .toString(), 1));
  91.       retval.set(s + "_ecc_delayed", findPattern(s
  92.           + "\s*:\s*(\d+\s+){1}(\d+)", sb.toString(), 2));
  93.       retval.set(s + "_rereads", findPattern(
  94.           s + "\s*:\s*(\d+\s+){2}(\d+)", sb.toString(), 2));
  95.       retval.set(s + "_GBs", findPattern(s
  96.           + "\s*:\s*(\d+\s+){5}(\d+.?\d*)", sb.toString(), 2));
  97.       retval.set(s + "_uncorrected",
  98.           findPattern(s + "\s*:\s*(\d+\s+){5}(\d+.?\d*){1}\s+(\d+)", sb
  99.               .toString(), 3));
  100.     }
  101.     // Hitachi IDE, SATA
  102.     retval.set("model", findPattern("Device\s*Model\s*:\s*(.*)", sb
  103.         .toString(), 1));
  104.     retval.set("serial", findPattern("Serial\s+number\s*:\s*(.*)", sb
  105.         .toString(), 1));
  106.     retval.set("protocol", findPattern("Transport\s+protocol\s*:\s*(.*)", sb
  107.         .toString(), 1));
  108.     retval.set("status", "PASSED".equalsIgnoreCase(findPattern(
  109.         "test\s*result\s*:\s*(.*)", sb.toString(), 1)) ? "OK" : "FAILED");
  110.     readColumns(retval, sb);
  111.     return retval;
  112.   }
  113.   /**
  114.    * Reads attributes in the following format:
  115.    * 
  116.    * ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  117.    * 3 Spin_Up_Time             0x0027   180   177   063    Pre-fail  Always       -       10265
  118.    * 4 Start_Stop_Count         0x0032   253   253   000    Old_age   Always       -       34
  119.    * 5 Reallocated_Sector_Ct    0x0033   253   253   063    Pre-fail  Always       -       0
  120.    * 6 Read_Channel_Margin      0x0001   253   253   100    Pre-fail  Offline      -       0
  121.    * 7 Seek_Error_Rate          0x000a   253   252   000    Old_age   Always       -       0
  122.    * 8 Seek_Time_Performance    0x0027   250   224   187    Pre-fail  Always       -       53894
  123.    * 9 Power_On_Minutes         0x0032   210   210   000    Old_age   Always       -       878h+00m
  124.    * 10 Spin_Retry_Count        0x002b   253   252   157    Pre-fail  Always       -       0
  125.    * 11 Calibration_Retry_Count 0x002b   253   252   223    Pre-fail  Always       -       0
  126.    * 12 Power_Cycle_Count       0x0032   253   253   000    Old_age   Always       -       49
  127.    * 192 PowerOff_Retract_Count 0x0032   253   253   000    Old_age   Always       -       0
  128.    * 193 Load_Cycle_Count       0x0032   253   253   000    Old_age   Always       -       0
  129.    * 194 Temperature_Celsius    0x0032   037   253   000    Old_age   Always       -       37
  130.    * 195 Hardware_ECC_Recovered 0x000a   253   252   000    Old_age   Always       -       2645
  131.    * 
  132.    * This format is mostly found in IDE and SATA disks.
  133.    * 
  134.    * @param er the EventRecord in which to store attributes found
  135.    * @param sb the StringBuffer with the text to parse
  136.    * 
  137.    * @return the EventRecord in which new attributes are stored.
  138.    */
  139.   private EventRecord readColumns(EventRecord er, StringBuffer sb) {
  140.     Pattern pattern = Pattern.compile("^\s{0,2}(\d{1,3}\s+.*)$",
  141.         Pattern.MULTILINE);
  142.     Matcher matcher = pattern.matcher(sb);
  143.     while (matcher.find()) {
  144.       String[] tokens = matcher.group(1).split("\s+");
  145.       boolean failed = false;
  146.       // check if this attribute is a failed one
  147.       if (!tokens[8].equals("-"))
  148.         failed = true;
  149.       er.set(tokens[1].toLowerCase(), (failed ? "FAILED:" : "") + tokens[9]);
  150.     }
  151.     return er;
  152.   }
  153.   /**
  154.    * Invokes query() to do the parsing and handles parsing errors for 
  155.    * each one of the disks specified in the configuration. 
  156.    * 
  157.    * @return an array of EventRecords that holds one element that represents
  158.    * the current state of the disk devices.
  159.    */
  160.   public EventRecord[] monitor() {
  161.     ArrayList<EventRecord> recs = new ArrayList<EventRecord>();
  162.     for (String device : devices) {
  163.       try {
  164.         recs.add(query(device));
  165.       } catch (Exception e) {
  166.         e.printStackTrace();
  167.       }
  168.     }
  169.     EventRecord[] T = new EventRecord[recs.size()];
  170.     return recs.toArray(T);
  171.   }
  172.   
  173.   /**
  174.    * Return a String with information about this class
  175.    * 
  176.    * @return A String describing this class
  177.    */
  178.   public String getInfo() {
  179.     String retval = "S.M.A.R.T. disk attributes parser for disks ";
  180.     for (String device : devices)
  181.       retval += device + " ";
  182.     return retval;
  183.   }
  184. }