Name

global.DiscoveryWindows2008StorageMultiSensor

Description

Processes WMI results for disks and file systems on Windows 2008 and earlier.

Script

/**
* Processes WMI results for Windows 2008 and earlier disks and file systems. Maps NAS and SAN dependencies if possible.
*
* @since fuji
* @author roy.laurie
*/
var DiscoveryWindows2008StorageMultiSensor = Class.create();

/* Win32_DiskDrive.InterfaceType => cmdb_ci_storage_device.device_interface */
DiscoveryWindows2008StorageMultiSensor._DISK_BUS_TYPE_INTERFACES = {
  SCSI: 'scsi',
  1394: 'ieee1394',
  USB: 'usb',
  HDC: null
};

DiscoveryWindows2008StorageMultiSensor._POWERSHELL_PROBE_ID = '43fbde9237422100dcd445cbbebe5dde';

DiscoveryWindows2008StorageMultiSensor.prototype = Object.extendsObject(DiscoveryWindowsStorageMultiSensor, {
  
  init: function() {
  	var arr = [ 'Win32_DiskDrive', 'Win32_DiskPartition', 'Win32_Volume', 'Win32_LogicalDiskToPartition', 'Win32_MappedLogicalDisk', 'Win32_LogicalDisk' ];
  	DiscoveryWindowsStorageMultiSensor.prototype.init.call(this, arr);
  },
  
  /**
   * Processes CMDB updates for storage devices.
   * @param Ci deviceCi
   * @param {} result The probe result
   */
  _processStorageDevices: function(deviceCi, result) {
  	var ciSchema = this.getCiSchema();
  	var storageReconciler = new DiscoveryStorageAllocationReconciler({ ciSchema: ciSchema });

  	for (var i = 0; i < result.Win32_DiskDrive.length; ++i) {
  		var disk = result.Win32_DiskDrive[i];
  		if (this.isDebugging())
  			Debug.logObject('Win32_DiskDrive', disk);

  		var deviceInterface = this._getDeviceInterfaceForBusType(disk.InterfaceType);
  		var makeModel = MakeAndModelJS.fromNames(disk.Manufacturer, disk.Model, 'hardware');
  		var table = this._getDiskTableForInterface(deviceInterface);

  		var iscsiSessionResult = this._findIscsiSessionResult(disk.DeviceID, result);
  		if (iscsiSessionResult !== null) {
  			table = 'cmdb_ci_iscsi_disk';
  			deviceInterface = 'iscsi';
  		}

  		var storageType = this._getStorageTypeForInterface(deviceInterface);

  		var diskCi = ciSchema.createCi(table, {
  			name: 'Disk #' + disk.Index, // may change across restarts
  			device_id: disk.DeviceID,
  			storage_type: storageType,
  			description: disk.Caption,
  			serial_number: disk.SerialNumber,
  			operational_status: ( disk.Status === 'OK' ? 1 : 2 ), // 1: operational, 2: non-operational
  			manufacturer: ''+makeModel.getManufacturerSysID(),
  			model_id: ''+makeModel.getModelNameSysID(),
  			computer: deviceCi,
  			device_interface: deviceInterface,
  			device_bus_id: disk.SCSIBus,
  			device_lun: disk.SCSILogicalUnit,
  			device_target_id: disk.SCSITargetId,
  			device_host_id: disk.SCSIPort,
  			device_name: disk.DeviceID // Used for reconcilation
  		});
  		
  		var size = new StorageDataSize(disk.Size, 'B');
  		size.applyToStorageDeviceSize(diskCi);

  		deviceCi.addReferral(diskCi);

  		// process some SAN data. FC handled separately
  		switch(table) {
  		case 'cmdb_ci_disk':
  			// populate deprecated fields until fuji+2 release
  			diskCi.data.drive_type = diskCi.data.storage_type;
  			break;

  		case 'cmdb_ci_iscsi_disk':
  			diskCi.data.iqn = iscsiSessionResult.targetIqn;
  			diskCi.data.initiator_iqn = iscsiSessionResult.initiatorIqn;
  				
  			// attempt to relate to upstream volume on array
  			try {
  				storageReconciler.createISCSIDiskCiToVolumeRel(diskCi);
  			} catch (e) {
  				// It is possible they have not discovered storage so not warning without debug on
  				if (this.isDebugging())
  					this.warn(e);
  			}
  			
  			break;
  		}

  		if (this.isDebugging())
  			Debug.logObject('Disk CI ' + i, diskCi.toShallowObj());
  	}
      
  },
  
  

  _findIscsiSessionResult: function(diskDeviceId, result) {
  	diskDeviceId = diskDeviceId.toLowerCase().replace(/\W/g, '');
  	for (var i = 0; i < result.iscsiSessions.length; ++i) {
  		var iscsiSession = result.iscsiSessions[i];
  		var sessionDeviceId = iscsiSession.deviceId.toLowerCase().replace(/\W/g, '');
  		if (sessionDeviceId === diskDeviceId)
  			return iscsiSession;
  	}

  	return null;
  },

  _processPartitions: function(deviceCi, result) {
  	var disks = deviceCi.getReferrals('cmdb_ci_storage_device');
  	var ciSchema = this.getCiSchema();

  	for (var i = 0; i < result.Win32_DiskPartition.length; ++i) {
  		var partition = result.Win32_DiskPartition[i];
  		if (this.isDebugging())
  			Debug.logObject('Win32_DiskPartition', partition);

  		// find the associated disk
  		var diskName = 'Disk #' + partition.DiskIndex;
  		var diskCi = null;
  		for (var j = 0; j < disks.length; ++j) {
  			if (disks[j].data.name === diskName) {
  				diskCi = disks[j];
  				break;
  			}
  		}

  		if (diskCi === null) {
  			this.warn('Win32_DiskDrive not found Win32_DiskPartition');
  			continue;
  		}

  		var partitionCi = ciSchema.createCi('cmdb_ci_disk_partition', {
  			name: diskCi.data.name + ' Partition #' + partition.Index,
  			computer: deviceCi,
  			disk: diskCi,
  			partition_number: partition.Index,
  			operational_status: ( partition.Status === 'OK' || gs.nil(partition.Status) ? 1 : 2 ),
  			start_offset: partition.StartingOffset,
  			end_offset: parseInt(partition.Size) + parseInt(partition.StartingOffset)
  		});

  		var size = new StorageDataSize(partition.Size, 'B');
  		size.applyToDiskPartitionSize(partitionCi);

  		diskCi.addReferral(partitionCi);
  		deviceCi.addReferral(partitionCi);

  		if (this.isDebugging())
  			Debug.logObject('Partition CI ' + i, partitionCi.toShallowObj());
  	}
  },

  _processFileSystems: function(deviceCi, result) {
  	var ciSchema = this.getCiSchema();
  	var volumeToDiskMapper = new DiscoveryVolumeToDiskMapper({ debug: this.isDebugging() });
  	var volumeSerialNumbers = {};
  	for (var i = 0 ; i < result.Win32_LogicalDisk.length; i++) {
  		var vSerialInfo = result.Win32_LogicalDisk[i];
  		var volId = vSerialInfo.DeviceID.trim();
  		volumeSerialNumbers[volId] = vSerialInfo.VolumeSerialNumber;
  	}
  	
  	var mountPoints = this._getVolumeIdsToMountPoints(result);
  	
  	for (i = 0; i < result.Win32_Volume.length; ++i) {
  		var volume = result.Win32_Volume[i];

  		if (this.isDebugging())
  			Debug.logObject('Win32_Volume', volume);

  		// remote file systems will use the NAS child table
  		var table = ( volume.DriveType === '4' ? 'cmdb_ci_nas_file_system' : 'cmdb_ci_file_system' ); // 4 = "Remote"

  		//TODO: There is a bug in PowerShell/WMI processing that is returning single characters as their decimal representation. Needs fixin'.
  		var absolutePath = null;
  		if (gs.nil(volume.DriveLetter) || volume.DriveLetter === '0') {
  			absolutePath = null;
  		} else if (isNaN(volume.DriveLetter)) {
  			absolutePath = volume.DriveLetter + '\\';
  		} else {
  			absolutePath = String.fromCharCode(volume.DriveLetter) + '\\';
  		}
  		
  		var volumeSerialNumber = null;
  		if (volume.DriveLetter && volumeSerialNumbers.hasOwnProperty(volume.DriveLetter))
  			volumeSerialNumber = volumeSerialNumbers[volume.DriveLetter];
  		
  		// Get real mount point by the volume id
  		var volumeId = this._getCleanVolumeId(volume.DeviceID);
  		var mountPoint = absolutePath;
  		if (mountPoints && mountPoints[volumeId])
  			mountPoint = mountPoints[volumeId];
  			
  		// create a new file system ci. reconciled by name and computer.
  		var fileSystemCi = ciSchema.createCi(table, {
  			computer: deviceCi,
  			mount_point: mountPoint,
  			name: ( absolutePath !== null ? absolutePath : volume.Label ),
  			media_type: this._getMediaTypeForVolume(volume.DriveType),
  			file_system: this._getFileSystemTypeForVolume(volume.FileSystem),
  			serial_number: volumeSerialNumber,
  			label: volume.Label
  		});
  		
  		var size = new StorageDataSize(volume.Capacity, 'B');
  		size.applyToStorageVolumeSize(fileSystemCi);
  		var free_space = new StorageDataSize(volume.FreeSpace, 'B');
  		free_space.applyToStorageVolumeFreeSpace(fileSystemCi);

  		deviceCi.addReferral(fileSystemCi); // reconcile against other file systems found on the device

  		// relate the provided_by back to this ci if found
  		var providedBy = this._findVolumeProvider(volume, result.Win32_LogicalDiskToPartition, deviceCi);
  		if (providedBy !== null) {
  			fileSystemCi.data.provided_by = providedBy;
  			providedBy.addReferral(fileSystemCi);

  			// update file system media type to reflect disk
  			if (providedBy.table === 'cmdb_ci_disk_partition' && providedBy.data.disk.data.storage_type === 'network')
  				fileSystemCi.data.media_type = 'network';
  				volumeToDiskMapper.relateStorageDevice(fileSystemCi);
  		}

  		if (this.isDebugging())
  			Debug.logObject('File System CI', fileSystemCi.toShallowObj());
  	}
  },

  

  /**
   * Finds the matching volume for the WMI results.
   */
  _findVolumeProvider: function(volumeResult, partitionToVolumeResults, deviceCi) {
  	// iterate through partition-to-volume mapping and find by volume object id
  	var partitionMaps = [];
  	for (var i = 0; i < partitionToVolumeResults.length; ++i) {
  		var partitionToVolume = partitionToVolumeResults[i];
  		var matches = partitionToVolume.Dependent.match(/\.DeviceID="(.*?)"$/);
  		if (matches === null)
  			continue;

  		var objectId = matches[1].replace(/\\\\/g, '\\');
  		if (objectId === volumeResult.DriveLetter)
  			partitionMaps.push(partitionToVolume);
  	}

  	//TODO: support raid - multiple partitions
  	if (partitionMaps.length !== 1)
  		return null;

  	var matches = partitionMaps[0].Antecedent.match(/\.DeviceID="Disk #(\d+), Partition #(\d+)"$/);
  	if (matches === null)
  		return null;

  	var diskIndex = matches[1].replace(/\\\\/g, '\\');
  	var partitionNumber = matches[2].replace(/\\\\/g, '\\');
  	var diskName = 'Disk #' + diskIndex;

  	var partitions = deviceCi.getReferrals('cmdb_ci_disk_partition');
  	for (var i = 0; i < partitions.length; ++i) {
  		var partitionCi = partitions[i];
  		var diskCi = partitionCi.data.disk;
  		if (partitionCi.data.partition_number === partitionNumber && diskCi.data.name === diskName)
  			return partitionCi;
  	}

  	return null;
  },

  _getDeviceInterfaceForBusType: function(busType) {
  	if (typeof DiscoveryWindows2008StorageMultiSensor._DISK_BUS_TYPE_INTERFACES[busType] === 'undefined')
  		return null;

  	return DiscoveryWindows2008StorageMultiSensor._DISK_BUS_TYPE_INTERFACES[busType];
  },
  
  

  type: 'DiscoveryWindows2008StorageMultiSensor'
});

Sys ID

d44c61b437112100dcd48c00dfbe5d0e

Offical Documentation

Official Docs: