/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.plugin.system;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hyperic.sigar.FileInfo;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemMap;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.util.StringUtil;
import org.hyperic.util.config.ConfigResponse;
import org.hyperic.util.config.EncodingException;
import org.hyperic.util.security.MD5;
import org.hyperic.hq.appdef.shared.AIServiceValue;
import org.hyperic.hq.product.PluginException;
import org.hyperic.hq.product.PluginManager;
import org.hyperic.sigar.win32.Pdh;
public class FileSystemDetector
extends SystemServerDetector {
private static final String PROP_DISCOVER_NFS =
"system.nfs.discover";
private boolean _discoverNfs;
public void init(PluginManager manager) throws PluginException {
super.init(manager);
_discoverNfs =
"true".equals(manager.getProperty(PROP_DISCOVER_NFS));
}
protected String getServerType() {
return SystemPlugin.FILE_SERVER_NAME;
}
protected ArrayList getSystemServiceValues(Sigar sigar, ConfigResponse config)
throws SigarException {
ArrayList services = new ArrayList();
if (isWin32()) {
List<String> disks = Arrays.asList(Pdh.getInstances("PhysicalDisk"));
for (String disk : disks) {
if (!disk.equalsIgnoreCase("_total")) {
AIServiceValue svc = createSystemService(SystemPlugin.PHYSICAL_DISK_SERVICE, getFullServiceName(disk), "name", disk);
services.add(svc);
}
}
disks = Arrays.asList(Pdh.getInstances("LogicalDisk"));
for (String disk : disks) {
if (!disk.equalsIgnoreCase("_total")) {
AIServiceValue svc = createSystemService(SystemPlugin.LOGICAL_DISK_SERVICE, getFullServiceName("Logical Disk "+disk), "name", disk);
services.add(svc);
}
}
} else {
List<String> devices = LinuxUtils.getBlockDevicesList();
for (String dev : devices) {
log.info("[getSystemServiceValues] dev='" + dev + "'");
AIServiceValue svc = createSystemService(SystemPlugin.BLOCK_DEVICE_SERVICE, getFullServiceName("Block Device /dev/"+dev), "name", dev);
services.add(svc);
}
}
FileSystem[] fslist = sigar.getFileSystemList();
for (int i=0; i<fslist.length; i++) {
FileSystem fs = fslist[i];
String dirName = fs.getDirName();
switch (fs.getType()) {
case FileSystem.TYPE_LOCAL_DISK:
case FileSystem.TYPE_NETWORK:
break;
default:
continue;
}
String genericType = fs.getTypeName();
String type = fs.getSysTypeName();
String mntInfo = "";
//e.g. avoid "C:\ mounted on C:\"
if (!fs.getDevName().equals(dirName)) {
mntInfo = " mounted on " + dirName;
}
String info =
"File System " + fs.getDevName() +
mntInfo +
" (" + genericType + "/" + type + ")";
if ((fs.getType() == FileSystem.TYPE_NETWORK) &&
!_discoverNfs)
{
getLog().debug(PROP_DISCOVER_NFS +
"=false, skipping " + info);
continue;
}
AIServiceValue svc =
createSystemService(SystemPlugin.FILE_MOUNT_SERVICE,
getFullServiceName(info),
SystemPlugin.PROP_FS,
dirName);
services.add(svc);
}
String[] fileTypes = {
SystemPlugin.FILE_SERVICE,
SystemPlugin.DIR_SERVICE,
SystemPlugin.DIR_TREE_SERVICE,
SystemPlugin.SCRIPT_SERVICE,
};
for (int i=0; i<fileTypes.length; i++) {
String type = fileTypes[i];
services.addAll(getFileServices(sigar, type));
services.addAll(getFileServiceImports(sigar, type));
}
return services;
}
private boolean canRead(File file) {
if (!file.exists()) {
log.warn(file + ": does not exist");
return false;
}
if (!file.canRead()) {
log.warn(file + ": cannot read");
return false;
}
return true;
}
private List getFileServiceImports(Sigar sigar, String type) {
List services = new ArrayList();
String prop = "system." + type + ".import";
String val = getManagerProperty(prop);
if (val == null) {
return services;
}
log.debug("Importing " + prop + "=" + val);
List files = StringUtil.explode(val, ",");
boolean isDirType =
type.indexOf(SystemPlugin.DIR_NAME) != -1;
for (int i=0; i<files.size(); i++) {
String path = (String)files.get(i);
boolean recurse = path.charAt(0) == '+';
if (recurse) {
path = path.substring(1);
}
File file = new File(path);
if (!canRead(file)) {
continue;
}
boolean isDir = file.isDirectory();
if (isDirType && !isDir) {
log.warn(file + ": not a directory");
continue;
}
//as-is
if ((isDirType && isDir) || !isDir) {
AIServiceValue svc =
createSystemService(type, path,
SystemPlugin.PROP_PATH, path);
setFileProperties(sigar, svc, path);
services.add(svc);
continue;
}
//import a directory of files or scripts
addFileServices(services, recurse, file, sigar, type);
}
return services;
}
private void addFileServices(List services, boolean recurse,
File dir, Sigar sigar, String type) {
String[] dents = dir.list();
if (dents == null) {
log.warn(dir + ": failed to list");
return;
}
for (int i=0; i<dents.length; i++) {
File ent = new File(dir, dents[i]);
String path = ent.getPath();
if (!canRead(ent)) {
continue;
}
if (ent.isDirectory()) {
if (recurse) {
addFileServices(services, recurse,
ent, sigar, type);
}
continue;
}
AIServiceValue svc =
createSystemService(type, path,
SystemPlugin.PROP_PATH, path);
setFileProperties(sigar, svc, path);
services.add(svc);
}
}
//File services are created by hand, the FileControlPlugin
//registers these services w/ SystemServerDetector so we
//can auto-discovery inventory properties here
private List getFileServices(Sigar sigar, String type) {
boolean isDebug = log.isDebugEnabled();
List serviceConfigs = getServiceConfigs(type);
List services = new ArrayList();
for (int i=0; i<serviceConfigs.size(); i++) {
ConfigResponse serviceConfig =
(ConfigResponse)serviceConfigs.get(i);
String name =
serviceConfig.getValue(SystemPlugin.PROP_RESOURCE_NAME);
String file =
serviceConfig.getValue(SystemPlugin.PROP_PATH);
AIServiceValue svc = createSystemService(type, name);
if (isDebug) {
log.debug("Getting cprops for " +
name + " " + type + "=" + file);
}
setFileProperties(sigar, svc, file);
services.add(svc);
}
return services;
}
private void setFileProperties(Sigar sigar, AIServiceValue svc, String file) {
ConfigResponse cprops = new ConfigResponse();
boolean isDirectory = new File(file).isDirectory();
if (!isDirectory) {
try {
cprops.setValue("md5",
MD5.getDigestString(new File(file)));
} catch (IOException e) {
getLog().debug("Error getting md5 for " + file + ": " + e);
}
}
if (!isWin32()) { //XXX not quite right on win32
try {
FileInfo info = sigar.getFileInfo(file);
cprops.setValue("permissions", info.getPermissionsString());
} catch (SigarException e) {
}
}
try {
FileSystemMap mounts = sigar.getFileSystemMap();
FileSystem fs = mounts.getMountPoint(file);
if (fs != null) {
cprops.setValue("fs", fs.getDirName());
}
} catch (SigarException e) {
}
try {
svc.setCustomProperties(cprops.encode());
} catch (EncodingException e) {
getLog().error("Error encoding cprops: " + e.getMessage());
}
}
}