Name

global.DiscoveryWindowsStorageMultiSensor

Description

No description available

Script

var DiscoveryWindowsStorageMultiSensor = Class.create();


/* cmdb_ci_disk.interface => child table of cmdb_ci_storage_device */
DiscoveryWindowsStorageMultiSensor._DEVICE_INTERFACE_TABLES = {
  iscsi: 'cmdb_ci_iscsi_disk',
  fc: 'cmdb_ci_fc_disk',
  raid: 'cmdb_ci_storage_device'
};

/* MSFT_Volume.FileSystem => cmdb_ci_file_system.type */
DiscoveryWindowsStorageMultiSensor._BUS_STORAGE_TYPES = {
  iscsi: 'network',
  fc: 'network',
  raid: 'raid'
};

/* MSFT_Volume.FileSystem => cmdb_ci_file_system.type */
DiscoveryWindowsStorageMultiSensor._VOLUME_DRIVE_TYPE_MEDIA = {
  0: null, // Unknown
  1: null, // Invalid Root Path
  2: 'removable', // Removable,
  3: 'fixed', // Fixed
  4: 'network', // Network
  5: 'cd', // CD-ROM
  6: 'ram' // RAM Disk
};

/* MSFT_Volume.FileSystem => cmdb_ci_file_system.type */
DiscoveryWindowsStorageMultiSensor._VOLUME_FILE_SYSTEMS = {
  NTFS: 'ntfs',
  UDF: 'udf',
  FAT: 'fat'
};

DiscoveryWindowsStorageMultiSensor.prototype = Object.extendsObject(DiscoveryMultiSensor, {
  init: function(resultsFields) {
  	DiscoveryMultiSensor.prototype.init.call(this);
  	this._result = {};
  	this._resultsFields = resultsFields;
  },

  /**
   * Multisensors call this method multiple times, once for each sub-probe.
   * We simply aggregate results here and then process them all at once in after().
   */
  process: function(result) {
  	this.setDefaultSave(false); // prevent multisensor from calling update()

  	DiscoveryMultiSensor.prototype.process.apply(this, arguments);

  	// merge each reuslt into the aggregate instance variable for use in after()
  	this._result = JSUtil.union(this._result, result.results.result);
  },

  after: function() {
  	DiscoveryMultiSensor.prototype.after.apply(this, arguments);

  	if (!this._result.Win32_DiskDrive)
  		return;

  	this._process(this._result);

  	this.update(); // call manually
  	this._reconcileExports();
  },

  _process: function(results) {
  	// prepare result data
  	results.iscsiSessions = [];
  	results.fcinfoDetails = [];
  	results.fcinfoPorts = [];
  	results.fcinfoMappings = [];

  	if (typeof results.output !== 'undefined') {
  		var jsobj = new JSON().decode(results.output);
  		results.iscsiSessions = ( jsobj.current.results.iscsi.iscsiSessions || [] );
  		results.fcinfoDetails = jsobj.current.results.fcinfoDetails;
  		results.fcinfoPorts = jsobj.current.results.fcinfoPorts;
  		results.fcinfoMappings = jsobj.current.results.fcinfoMappings;
  					
  		delete results.output;
  	}
  	
  	// prepare result data
  	this._ensureArray(results, this._resultsFields);

  	var deviceCi = this.getDeviceCi();

  	// add disks to device ci
  	this._processStorageDevices(deviceCi, results);
  	// add partitions to device ci
  	this._processPartitions(deviceCi, results);
  	// add file systems to device ci
  	this._processFileSystems(deviceCi, results);
  	// add NAS file systems to device ci
  	this._processNasFileSystems(deviceCi, results); 
  	// add FC HBAs
  	this._processFcAdapters(deviceCi, results);
  	// add FC Ports
  	this._processFcPorts(deviceCi, results);
  	// map ports to disks
  	this._processFcDisksToPorts(deviceCi, results);
  	
  	
  	// aggregate all attatched disk space and update device capacity as an integer
  	var totalBytes = DiscoveryStorageUtilities.getAggregateDataSize(deviceCi);
  	deviceCi.data.disk_space = new StorageDataSize(totalBytes).to(StorageDataSize.Units.GB) | 0;
  },

  _processFcAdapters: function(deviceCi, results) {
  	var ciSchema = this.getCiSchema();
  	var adapterCis = [];
  	
  	for (var i = 0; i < results.fcinfoDetails.length; ++i) {
  		var adapter = results.fcinfoDetails[i];

  		if (this.isDebugging())
  			Debug.logObject('HBA result', adapter);

  		// each hba may be logically presented, rather than physically. identify on serial
  		var found = false;
  		for (var j = 0; j < adapterCis.length; ++j) {
  			if (adapterCis[j].data.serial_number === adapter.sernum) {
  				// skip. save the adapter name, though
  				adapterCis[j]._temp.adapterNames.push(adapter.adapter);
  				found = true;
  				break;
  			}
  		}
  		
  		if (found)
  			continue;
  		
  		var makeModel = MakeAndModelJS.fromNames(adapter.manfac, adapter.model, 'hardware');
  		var manufacturer = '';
  		if (JSUtil.notNil(adapter.manfac))
  			manufacturer = adapter.manfac.split(/ /)[0];
  		
  		var ciName = manufacturer + ' ' + adapter.sernum;

  		var adapterCi = ciSchema.createCi('cmdb_ci_storage_hba', {
  			computer: deviceCi,
  			device_id: adapter.sernum,
  			manufacturer: ''+makeModel.getManufacturerSysID(),
  			model_id: ''+makeModel.getModelNameSysID(),
  			serial_number: adapter.sernum,
  			name: ciName
  		});

  		deviceCi.addReferral(adapterCi);
  		adapterCi._temp = { adapterNames: [ adapter.adapter ] }; // for fc port mapping
  		adapterCis.push(adapterCi);

  		if (this.isDebugging())
  			Debug.logObject('HBA CI', adapterCi.toShallowObj());
  	}
  },

  _processFcPorts: function(deviceCi, results) {
  	var ciSchema = this.getCiSchema();
  	var adapterCis = deviceCi.getReferrals('cmdb_ci_storage_hba');
  	
  	for (var i = 0; i < results.fcinfoPorts.length; ++i) {
  		var port = results.fcinfoPorts[i];

  		if (this.isDebugging())
  			Debug.logObject('FC Info Details', port);

  		// find the corresponding HBA by adapter name (temp field)
  		var adapterCi = null;
  		for (var j = 0; j < adapterCis.length; ++j) {
  			if (JSUtil.contains(adapterCis[j]._temp.adapterNames, port.adapter)) {
  				adapterCi = adapterCis[j];
  				break;
  			}
  		}

  		// skip this port if we unexpectedly cannot find the hba
  		if (adapterCi === null) {
  			this.warn('Unable to find FC HBA for FC Port: ' + port.PortWWN);
  			continue;
  		}

  		var wwpn = StorageWWN.parse(port.PortWWN);
  		var portType = new DiscoveryFcPortType(port.Type.split(/_/)[0]).toString(); // "N_Port" --> "N"
  		
  		var speed = null;
  		try {
  			if (port.Speed.length !== 0)
  				speed = new DiscoveryDataRate(port.Speed, 'GFC');
  		} catch (e) { /* squelch. maybe "unkn" or blank. */ }
  		
  		var portCi = ciSchema.createCi('cmdb_ci_fc_port', {
  			computer: deviceCi,
  			controller: adapterCi,
  			wwpn: wwpn,
  			wwnn: StorageWWN.parse(port.WWN),
  			port_type: portType,
  			speed: ( speed ? speed.to(DiscoveryDataRate.Units.GFC) + ' GFC' : null ),
  			operational_status: ( port.State === 'online' ? 1 : 0 ),
  			name: 'FC Port ' + wwpn
  		});

  		deviceCi.addReferral(portCi);
  		adapterCi.addReferral(portCi);

  		if (this.isDebugging())
  			Debug.logObject('FC Port CI', portCi.toShallowObj());
  	}
  },
  
  _processFcDisksToPorts: function(deviceCi, results) {
  	var ciSchema = this.getCiSchema();
  	var diskCis = deviceCi.getReferrals('cmdb_ci_storage_device');
  	var portCis = deviceCi.getReferrals('cmdb_ci_fc_port');
  	var storageReconciler = new DiscoveryStorageAllocationReconciler();
  	
  	var WWNMap = {};      
  	getWWNMap();
  	
  	for (var i = 0; i < results.fcinfoMappings.length; ++i) {
  		var adapter = results.fcinfoMappings[i];

  		if (this.isDebugging())
  			Debug.logObject('FC Mapped Adapter', adapter);
  		
  		for (var d = 0; d < adapter.devices.length; ++d) {
  			var device = adapter.devices[d];

  			if (this.isDebugging())
  				Debug.logObject('FC Mapped Device', device);
  			
  			// find the storage device CI based on provided device id
  			var diskCi = null;
  			var deviceName = device.DeviceName.toLowerCase();
  			for (var s = 0; s < diskCis.length; ++s) {
  				if (diskCis[s].data.device_name.toLowerCase() === deviceName) {
  					diskCi = diskCis[s];
  					continue;
  				}
  			}
  			
  			if (diskCi === null) {
  				this.warn('FC Disk CI not found for DeviceName: ' + device.DeviceName);
  				continue;
  			}
  			
  			var mapping = device.mappings[0]; // active path first
  			
  			if (this.isDebugging())
  				Debug.logObject('FC Mapping', mapping);
  			
  			var targetWWPN = new StorageWWN(mapping.PortWWN).toString();
  			var targetWWNN = new StorageWWN(mapping.WWN).toString();
  			
  			// change the table / type of the disk
  			diskCi.table = 'cmdb_ci_fc_disk';
  			diskCi.data.storage_type = 'network';
  			diskCi.data.device_interface = 'fc';
  							
  			// related to exported volume on storage array, if possible
  			
  			diskCi.data.lun = mapping.L;
  			
  			// A fc target entry
  			var targetCi = ciSchema.createCi('cmdb_fc_target', { 
  					wwnn: targetWWNN,
  					wwpn: targetWWPN
  			});
  			diskCi.addReferral(targetCi);
  			
  			// A initiator entry
  			var initiator = WWNMap[mapping.WWN + "-" + mapping.PortWWN];
  			var initiatorWWN = StorageWWN.parse(initiator.WWN);
  			var initiatorWWPN = StorageWWN.parse(initiator.WWPN);
  			var initiatorCi = ciSchema.createCi('cmdb_fc_initiator', { 
  					wwnn: initiatorWWN,
  					wwpn: initiatorWWPN
  			});
  			diskCi.addReferral(initiatorCi);
  			
  			try {
  				storageReconciler.createFCDiskCiToVolumeRel(diskCi, new Array(targetWWPN), initiatorWWPN);
  			} catch (e) {
  				if (this.isDebugging())
  					this.warn(e);
  			}
  			
  			if (this.isDebugging())
  				Debug.logObject('FC Disk', diskCi.toShallowObj());
  		}
  	}
  	
  	// Get mapping from target WWNS to initiator WWNS
  	function getWWNMap() {

  		for (var i = 0; i < results.fcinfoPorts.length; i++) {
  			var port = results.fcinfoPorts[i];
  			for (var j=0; j < port.targetWWNS.length; j++) {
  				var targetWWN = port.targetWWNS[j];
  				WWNMap[targetWWN.WWN + "-" + targetWWN.PortWWN] = {WWN: port.WWN, WWPN: port.PortWWN};		
  			}
  		}		
  	}
  	
  },

  _getDeviceInterfaceForBusType: function(busType) {
  	// Needs to be overriden
  },

  _getDiskTableForInterface: function(iface) {
  	if (typeof DiscoveryWindowsStorageMultiSensor._DEVICE_INTERFACE_TABLES[iface] === 'undefined')
  		return 'cmdb_ci_disk';

  	return DiscoveryWindowsStorageMultiSensor._DEVICE_INTERFACE_TABLES[iface];
  },

  _getMediaTypeForVolume: function(volumeDriveType) {
  	if (typeof DiscoveryWindowsStorageMultiSensor._VOLUME_DRIVE_TYPE_MEDIA[volumeDriveType] === 'undefined')
  		return null;

  	return DiscoveryWindowsStorageMultiSensor._VOLUME_DRIVE_TYPE_MEDIA[volumeDriveType];
  },

  _getFileSystemTypeForVolume: function(volumeFileSystem) {
  	if (typeof DiscoveryWindowsStorageMultiSensor._VOLUME_FILE_SYSTEMS[volumeFileSystem] === 'undefined')
  		return null;

  	return DiscoveryWindowsStorageMultiSensor._VOLUME_FILE_SYSTEMS[volumeFileSystem];
  },

  _getStorageTypeForInterface: function(iface) {
  	if (typeof DiscoveryWindowsStorageMultiSensor._BUS_STORAGE_TYPES[iface] === 'undefined')
  		return 'logical';

  	return DiscoveryWindowsStorageMultiSensor._BUS_STORAGE_TYPES[iface];
  },

  _reconcileNas: function() {
  	var deviceId = this.getDeviceCi().data.sys_id;
  	var reconciler = new DiscoveryStorageAllocationReconciler();

  	var diskGr = new GlideRecord('cmdb_ci_nas_file_system');
  	diskGr.addQuery('computer', deviceId);
  	diskGr.query();

  	while (diskGr.next())
  		reconciler.reconcileFileSystem(diskGr);

  	reconciler.pruneAbsentMounts(deviceId, 'cmdb_ci_nas_file_system');
  },

  _ensureArray: function(result, fieldNames) {
  	for (var i = 0; i < fieldNames.length; ++i) {
  		var field = fieldNames[i];
  		result[field] = g_array_util.ensureArray(result[field]);
  	}
  },

  _processNasFileSystems: function (deviceCi, result){
      var ciSchema = this.getCiSchema();
      var storageReconciler = new DiscoveryStorageAllocationReconciler({ ciSchema: ciSchema });
      for (var i = 0; i < result.Win32_MappedLogicalDisk.length; ++i) {
  
          var df = result.Win32_MappedLogicalDisk[i];
          var nasInfo = storageReconciler.getNASInfo(df.ProviderName);
          if (!nasInfo)
              continue;
          
  		var dataSize = null;
  		try {
              dataSize = new StorageDataSize((df.Size || 0), StorageDataSize.Units.B);
          } catch (e) { /* do nothing */ }
              
          var freeDataSize = null;
  		try {
              freeDataSize = new StorageDataSize((df.FreeSpace || 0), StorageDataSize.Units.B);
          } catch (e) { /* do nothing */ }
              
          var fileSystemCi = ciSchema.createCi('cmdb_ci_nas_file_system', {
  			name: df.DeviceID,
  			mount_point: df.DeviceID,
  			file_system: df.FileSystem,
  			media_type: 'network',
  			computer: deviceCi,
  			nas_path: nasInfo.path,
  			nas_hostname : nasInfo.hostname ,
  			nas_ip_address : nasInfo.ip ? nasInfo.ip : null,
  			nas_protocol : df.FileSystem,
              
          });
              
          if (dataSize !== null)
              dataSize.applyToStorageVolumeSize(fileSystemCi);
              
          if (freeDataSize !== null)
              freeDataSize.applyToStorageVolumeFreeSpace(fileSystemCi);
              
          deviceCi.addReferral(fileSystemCi);
              
             
      }
  },
  _reconcileExports: function() {
  	var deviceId = ''+this.getCmdbCi();
  	var reconciler = new DiscoveryStorageAllocationReconciler();
  	reconciler.reconcileFileSystemByServer(deviceId);	
  },

  _getVolumeIdsToMountPoints: function(result){
      if (!result.hasOwnProperty("Win32_MountPoint"))
          return null;
  	
  	var mountPoints = {};

      for (var i = 0; i<result.Win32_MountPoint.length; i++) {
          var mountPointObj = result.Win32_MountPoint[i];

          // try to extract a Volume with ID if exists.
          var mountPointVolumeId = this._getCleanVolumeId(mountPointObj.Volume);
  					
  		var mountPoint = mountPointObj.Directory;	
  		// Grab the directory by name
  		matches = mountPoint.match(/Win32_Directory.Name=\"(.*)\"/i);
  		if (matches && matches[1])
  			mountPoint = matches[1];
  		
  		// Remove extra slashes if needed.
  		mountPoint = mountPoint.replace(/\\\\/g, "\\");
  		
  		mountPoints[mountPointVolumeId] = mountPoint;
      }

      return mountPoints;
  },
  
  _getCleanVolumeId: function(volumeId){
  	var matches = volumeId.match(/.*?(Volume\{.*\})/i);
  	if (matches && matches[1])
  		volumeId = matches[1];
  	
  	return volumeId;
  },
  
  type: 'DiscoveryWindowsStorageMultiSensor'
});

Sys ID

faffb67447510200d06d6f2ccee49051

Offical Documentation

Official Docs: