def _logWarn(errorCode, params, errorMessage): 'int, list(str), str -> None' if not (modeling.CmdbClassModel().version() >= 9.0): errorMessage = errormessages.makeErrorMessage( params[1].upper(), params[0], errormessages.ERROR_DISCOVERY_BY_PROTOCOL) logger.debugException(errorMessage) errobj = errorobject.createError(errorCode, params, errorMessage) logger.reportWarningObject(errobj)
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() fileSeparator = File.separator DebugMode = Framework.getParameter('DebugMode') userExtDir = CollectorsParameters.BASE_PROBE_MGR_DIR + CollectorsParameters.getDiscoveryResourceFolder() + fileSeparator filePathDir = userExtDir + 'TQLExport' + fileSeparator + 'hpsim' + fileSeparator + 'results' + fileSeparator directory = File(filePathDir) files = directory.listFiles() if files == None: logger.warn('Results XML not found. Perhaps no data was received from SIM or an error occurred in the SIM_Discovery script.') return ## Read ignored Ci types from integration configuration ignoredCiTypes = [] rawIgnoredCiTypes = Framework.getParameter('IgnoredCiTypes') tempIgnoredCiTypes = eval(rawIgnoredCiTypes) if tempIgnoredCiTypes is not None: for item in tempIgnoredCiTypes: item != 'None' and ignoredCiTypes.append(item) ## Identify UCMDB version ucmdbVersion = modeling.CmdbClassModel().version() try: ## Start the work for file in files: if file != None or file != '': builder = SAXBuilder() doc = builder.build(file) # Process CIs # info("Start processing CIs to update in the destination server...") allObjects = doc.getRootElement().getChild('data').getChild('objects').getChildren('Object') (objVector, ciDict) = processObjects(allObjects, ignoredCiTypes, ucmdbVersion) OSHVResult.addAll(objVector) # Process Relations # info("Start processing Relationships to update in the destination server...") allLinks = doc.getRootElement().getChild('data').getChild('links').getChildren('link') linkVector = processLinks(allLinks, ciDict) OSHVResult.addAll(linkVector) except: stacktrace = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) info(concatenate('Failure: ():\n', stacktrace)) if (DebugMode != None): DebugMode = DebugMode.lower() if DebugMode == "true": mam_utils.info ('[NOTE] UCMDB Integration is running in DEBUG mode. No data will be pushed to the destination server.') print OSHVResult.toXmlString() return None else: #print OSHVResult.toXmlString() return OSHVResult
def createClientServerDependentLink(self, OSHVResult, clientHostOsh, serverHostOSH, serverPort, portName): ucmdbVersion = modeling.CmdbClassModel().version() if ucmdbVersion >= 9: nodeDependencyLink = modeling.createLinkOSH( 'node_dependency', clientHostOsh, serverHostOSH) nodeDependencyLink.setAttribute('dependency_name', serverPort) nodeDependencyLink.setAttribute('dependency_source', portName) OSHVResult.add(nodeDependencyLink) else: dependencyLink = modeling.createLinkOSH('dependency', clientHostOsh, serverHostOSH) dependencyLink.setAttribute('dependency_name', serverPort) dependencyLink.setAttribute('dependency_source', portName) OSHVResult.add(dependencyLink)
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() protocol = 'SNMP' ip_address = Framework.getDestinationAttribute('ip_address') discoverRoute = Framework.getParameter('discoverRoute') ucmdbversion = modeling.CmdbClassModel().version() hostIdStr = Framework.getDestinationAttribute('hostId') hostId = CmdbObjectID.Factory.restoreObjectID(hostIdStr) hostIsComplete = Framework.getDestinationAttribute('hostIsComplete') client = None try: client = Framework.createClient() snmpDiscover(client, ip_address, discoverRoute, hostId, OSHVResult, hostIsComplete, ucmdbversion) except Exception, ex: errorStr = str(ex.getMessage()) logger.debugException('Unexpected SNMP_AGENT Exception:' + errorStr) errormessages.resolveAndReport(errorStr, protocol, Framework)
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() ipAddress = Framework.getDestinationAttribute('ip_address') hostId = Framework.getDestinationAttribute('hostId') hostModel = Framework.getDestinationAttribute('hostModel') hostOs = Framework.getDestinationAttribute('hostOs') snmpDescription = Framework.getDestinationAttribute('smpDescription') hostOSH = modeling.createOshByCmdbIdString('switch', hostId) ucmdbversion = modeling.CmdbClassModel().version() snmpClient = None try: snmpClient = Framework.createClient() device_type_str = '%s%s%s' % (hostModel.lower(), hostOs.lower(), snmpDescription.lower()) if device_type_str.find('atalyst') != -1 or device_type_str.find( 'cisco') != -1: doAll(snmpClient, hostOSH, OSHVResult, ucmdbversion, Framework) else: vlan_discoverer = VlanDiscoverer(snmpClient, hostOSH, Framework) try: vlan_discoverer.discover_vlans() except NoVlansException: if device_type_str.find('hp') != -1 or device_type_str.find( 'procurve') != -1: #old HP ProCurve switches use HP private MIBs vlan_discoverer = HpProCurveVlanDiscoverer( snmpClient, hostOSH, Framework) vlan_discoverer.discover_vlans() except: Framework.reportError('Failed to discover ip: %s' % ipAddress) logger.debugException('Failed to discover ip: %s' % ipAddress) if snmpClient != None: snmpClient.close() return OSHVResult
def parseOpmnXml(opmnXML, HOST_IP, ORACLE_HOME, MANAGER_PORT, shellUtils, OSHVResult, Framework): builder = SAXBuilder(0) doc = builder.build(StringReader(opmnXML)) root = doc.getRootElement() ucmdbVersion = modeling.CmdbClassModel().version() processManager = root.getChildren() processManagerIterator = processManager.iterator() while processManagerIterator.hasNext(): currProcessManager = processManagerIterator.next() currElementName = currProcessManager.getName() if currElementName == 'process-manager': iasInstance = currProcessManager.getChildren() iasInstanceIterator = iasInstance.iterator() while iasInstanceIterator.hasNext(): currIasInstance = iasInstanceIterator.next() if currIasInstance.getName() == 'ias-instance': OracleApplicationServerName = currIasInstance.getAttributeValue('name') or currIasInstance.getAttributeValue('id') or 'Default Server' discoveredHost = modeling.createHostOSH(HOST_IP) # Create Oracle IAS oracleIASOSH = modeling.createJ2EEServer('oracleias', HOST_IP, int(MANAGER_PORT), discoveredHost, OracleApplicationServerName) OSHVResult.add(oracleIASOSH) iasComponent = currIasInstance.getChildren() iasComponentIterator = iasComponent.iterator() while iasComponentIterator.hasNext(): currIasComponent = iasComponentIterator.next() if 'ias-component' == currIasComponent.getName(): groupName = currIasComponent.getAttributeValue('id') # Create OC4J Group oc4jGroupOSH = ObjectStateHolder('oc4jgroup') oc4jGroupOSH.setContainer(oracleIASOSH) oc4jGroupOSH.setAttribute('data_name', groupName) OSHVResult.add(oc4jGroupOSH) #'process-type' processType = currIasComponent.getChildren() processTypeIterator = processType.iterator() while processTypeIterator.hasNext(): currProcessType = processTypeIterator.next() oc4jName = currProcessType.getAttributeValue('id') moduleId = currProcessType.getAttributeValue('module-id') if 'OC4J' == moduleId: oc4jOSH = ObjectStateHolder('oc4j') oc4jOSH.setContainer(oc4jGroupOSH) oc4jOSH.setAttribute('data_name', oc4jName) OSHVResult.add(oc4jOSH) try: serverXML = shellUtils.safecat('%s/j2ee/%s/config/server.xml' % (ORACLE_HOME, oc4jName)) tg = '<application name="(\w+)"' compiled = re.compile(tg,re.S) matches = compiled.findall(serverXML) appList = {} for match in matches: if ucmdbVersion < 9: applicationOSH = modeling.createApplicationOSH('application', match, oc4jOSH) else: applicationOSH = ObjectStateHolder('oc4j_app') applicationOSH.setAttribute('data_name',match) applicationOSH.setContainer(oc4jOSH) # OSHVResult.add(applicationOSH) appList[match] = applicationOSH except: logger.debugException() logger.warn('Failed to get server.xml') # Check if it holds web service wsdlDir = shellUtils.rebuildPath('%s/j2ee/%s/application-deployments/' % (ORACLE_HOME, OracleApplicationServerName)) fileMon = file_mon_utils.FileMonitor(Framework, shellUtils, OSHVResult, None, None) files = fileMon.getFilesInPath(wsdlDir, '*.wsdl') if (files == []): wsdlDir = shellUtils.rebuildPath('%s/j2ee/%s/application-deployments/' % (ORACLE_HOME, oc4jName)) logger.info('Pi Debug - parseOpmnXml() - trying with wsdlDir = %s' % wsdlDir) files = fileMon.getFilesInPath(wsdlDir, '*.wsdl') wsdlDirRes = '\n'.join(files) if wsdlDirRes.find('File Not Found') != -1: # NO WSDL continue else: # WSDL handleWSDL(HOST_IP, MANAGER_PORT, wsdlDirRes, wsdlDir, appList, shellUtils, OSHVResult)
def doHPCmd(client, ntcmd_obj, ip_address, langBund, Framework, host_cmdbid=None, host_key=None, host_macs=None, uduid=None, nat_ip=None): 'Shell, osh, str, Properties, Framework, .. -> oshVector' resultVector = ObjectStateHolderVector() ipAddress = ip_addr.IPAddress(ip_address) wmiProvider = wmiutils.WmicProvider(client) hostDiscoverer = WmiHostDiscoverer(wmiProvider) hostDo = hostDiscoverer.discover() hostDiscoverer = HostDiscovererByShell(client, langBund, Framework, hostDo) hostDiscoverer.discover() hostDo = hostDiscoverer.getResults() wmiDnsServersDiscoverer = WmiDnsServersDiscoverer(wmiProvider, ipAddress) wmiDnsServersDiscoverer.discover() dnsServersIpList = wmiDnsServersDiscoverer.getResults() if not dnsServersIpList: dnsServersDiscoverer = DnsServersDiscoverer(client, ipAddress, langBund, Framework) dnsServersDiscoverer.discover() dnsServersIpList = dnsServersDiscoverer.getResults() winsWmiServersDiscoverer = WmiWinsServersDiscoverer(wmiProvider, ipAddress) winsWmiServersDiscoverer.discover() winsServersIpList = winsWmiServersDiscoverer.getResults() if not winsServersIpList: winsServerDiscoverer = WinsServerDicoverer(client, ipAddress, langBund, Framework) winsServerDiscoverer.discover() winsServersIpList = winsServerDiscoverer.getResults() dhcpWmiServersDiscoverer = WmiDhcpServersDiscoverer(wmiProvider, ipAddress) dhcpWmiServersDiscoverer.discover() dhcpServersIpList = dhcpWmiServersDiscoverer.getResults() if not dhcpServersIpList: dhcpServerDiscoverer = DhcpServerDiscoverer(client, ipAddress, langBund, Framework) dhcpServerDiscoverer.discover() dhcpServersIpList = dhcpServerDiscoverer.getResults() interfaceDiscoverer = WmiInterfaceDiscoverer(wmiProvider, ipAddress) try: interfaceDiscoverer.discover() logger.debug('Interfaces successfully discovered via wmic.') try: shellIfaceDiscoverer = IpConfigInterfaceDiscoverer( client, ipAddress, Framework, langBund) shellIfaceDiscoverer.discover() ifaces = shellIfaceDiscoverer.getResults() interfaceDiscoverer.interfacesList.extend(ifaces) except: logger.debugException('') except: msg = logger.prepareFullStackTrace('') logger.debugException(msg) logger.warn( 'Failed getting interfaces information via wmic. Falling back to ipconfig.' ) interfaceDiscoverer = IpConfigInterfaceDiscoverer( client, ipAddress, Framework, langBund) interfaceDiscoverer.discover() hostDo.ipIsVirtual = interfaceDiscoverer.isIpVirtual() hostDo.ipIsNATed = interfaceDiscoverer.isIpNATed(nat_ip) interfacesList = interfaceDiscoverer.getResults() ucmdbversion = modeling.CmdbClassModel().version() topoBuilder = TopologyBuilder(interfacesList, hostDo, ipAddress, ntcmd_obj, dnsServersIpList, dhcpServersIpList, winsServersIpList, host_cmdbid, host_key, host_macs, ucmdbversion) topoBuilder.build() # access built host OSH to update UD UID attribute if topoBuilder.hostOsh and uduid: _updateHostUniversalDiscoveryUid(topoBuilder.hostOsh, uduid) topoBuilder.addResultsToVector(resultVector) return resultVector
def __init__(self, destinationIp): self.destinationIp = destinationIp self.interfacesList = [] self.ucmdbVersion = modeling.CmdbClassModel().version() self.ipIsVirtual = None self.ipIsNATed = None
def report(vector, hostOsh, sizeInKb): 'ObjectStateHolderVector, ObjectStateHolder, int' if modeling.CmdbClassModel().version() < 9: _report80(vector, hostOsh, sizeInKb) else: _report90(vector, hostOsh, sizeInKb)
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() ipAddress = Framework.getDestinationAttribute('ip_address') credentialsId = Framework.getDestinationAttribute('credentialsId') ucmdbversion = modeling.CmdbClassModel().version() snmpCommunityPostfixList = '' try: snmpCommunityPostfixList = Framework.getTriggerCIDataAsList('snmpCommunityPostfix') if not snmpCommunityPostfixList: raise Exception, "No Vlans defined on switch" except: Framework.reportError('Failed to discover destination. No Vlans properly configured.') return OSHVResult hostId = Framework.getDestinationAttribute('hostId') hostOSH = modeling.createOshByCmdbIdString('host', hostId) vlan_context_dict = {} snmp_version = Framework.getProtocolProperty(credentialsId, "snmpprotocol_version") if snmp_version == 'version 3': client = Framework.createClient() vlan_context_dict = snmputils.get_snmp_vlan_context_dict(client) client and client.close() vlanOSH = None failedToDiscoverCounter = 0 for snmpCommunityPostfix in snmpCommunityPostfixList: vlanOSH = modeling.createVlanOsh(snmpCommunityPostfix, hostOSH) vlanOSH.setContainer(hostOSH) properties = Properties() if credentialsId and ipAddress: properties.setProperty('ip_address', ipAddress) properties.setProperty(BaseClient.CREDENTIALS_ID, credentialsId) if (snmpCommunityPostfix != None) and (snmpCommunityPostfix != ''): if snmp_version == 'version 3': if not vlan_context_dict: logger.warn("Vlan Conext is not present on the device. No Vlan details might be discovered") continue vlan_context = vlan_context_dict.get(snmpCommunityPostfix) if not vlan_context: logger.warn("Failed to find configured Vlan context for Vlan %s. Vlan will be skipped" % snmpCommunityPostfix) continue properties.setProperty(SnmpQueries._postfix, '%s' % vlan_context) else: properties.setProperty(SnmpQueries._postfix, '%s%s' % ('@', snmpCommunityPostfix)) snmpClient = None try: snmpClient = Framework.createClient(properties) #SnmpConnectionTester(snmpClient).testSnmpConnection() doAll(snmpClient, hostOSH, vlanOSH, OSHVResult, ucmdbversion) Framework.sendObjects(OSHVResult) Framework.flushObjects() logger.debug('Vlan %s successfully discovered. Result vector contains %d objects.' % (snmpCommunityPostfix, OSHVResult.size())) OSHVResult = ObjectStateHolderVector() except: logger.debugException('') failedToDiscoverCounter =+ 1 logger.debugException('Failed to discover ip: %s on Vlan#: %s. ' % (ipAddress, snmpCommunityPostfix)) if snmpClient != None: snmpClient.close() if failedToDiscoverCounter == len(snmpCommunityPostfixList): Framework.reportError('Failed to discover all Vlans on the destination.') elif failedToDiscoverCounter: Framework.reportWarning('Failed to discover one or more Vlans on the destination') if snmpClient != None: snmpClient.close() return OSHVResult
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() DISCOVERED_IP = Framework.getDestinationAttribute('ip_address') DISCOVERED_IP_ID = Framework.getDestinationAttribute('ip_id') # ip = modeling.createOshByCmdbIdString('ip_address', DISCOVERED_IP_ID) ucmdbVersion = modeling.CmdbClassModel().version() if ucmdbVersion >= 9: ipClass = 'ip_address' else: ipClass = 'ip' protocols = Framework.getAvailableProtocols( DISCOVERED_IP, ClientsConsts.SNMP_PROTOCOL_NAME) if protocols.__len__() == 0: errStr = 'No credentials defined for the triggered ip' logger.debug(errStr) Framework.reportWarning(errStr) else: for protocol in protocols: sysplexNameList = None lparIpList = None snmpOSH = modeling.createSnmpOSH(DISCOVERED_IP, None) client = None try: client = Framework.createClient(protocol) logger.debug('got snmp agent for: ', DISCOVERED_IP) isMultiOid = client.supportMultiOid() sysplexNameList = client.executeQuery( '1.3.6.1.4.1.2.6.19.2.2.2.41,1.3.6.1.4.1.2.6.19.2.2.2.41,string,1.3.6.1.4.1.2.6.19.2.2.2.40,string' ) #@@CMD_PERMISION snmp protocol execution sysplexNameList = sysplexNameList.asTable() lparIpList = client.executeQuery( '1.3.6.1.2.1.4.20.1.1,1.3.6.1.2.1.4.20.1.2,string' ) #@@CMD_PERMISION snmp protocol execution lparIpList = lparIpList.asTable() mainframeMacList = client.executeQuery( '1.3.6.1.2.1.2.2.1.6,1.3.6.1.2.1.2.2.1.7,hexa' ) #@@CMD_PERMISION snmp protocol execution mainframeMacList = mainframeMacList.asTable() snmpOSH.setAttribute('application_port', client.getPort()) snmpOSH.setAttribute('application_timeout', client.getTimeout()) snmpOSH.setAttribute('snmp_port', client.getPort()) snmpOSH.setAttribute('credentials_id', client.getCredentialId()) snmpOSH.setAttribute('snmp_retry', client.getRetries()) snmpOSH.setAttribute('snmp_timeout', client.getTimeout()) if isMultiOid == 1: snmpOSH.setBoolAttribute('snmp_supportmultioid', 1) else: snmpOSH.setBoolAttribute('snmp_supportmultioid', 0) except: logger.debugException('Unexpected SNMP_AGENT Exception:') continue if client != None: client.close() mainframeKey = getMainframeKey(mainframeMacList) if mainframeKey: mainframeOSH = modeling.createCompleteHostOSH( 'mainframe', mainframeKey, machineName=mainframeKey) modeling.setHostOsFamily(mainframeOSH, 'mainframe') OSHVResult.add(mainframeOSH) for currSysplex in sysplexNameList: if logger.isDebugEnabled(): logger.debug('SYSPLEX : ', currSysplex[1]) logger.debug('LPAR : ', currSysplex[2]) logger.debug('MainframeKEY : ', mainframeKey) lparKey = mainframeKey + ':' + currSysplex[2] lparOSH = modeling.createCompleteHostOSH( 'lpar', lparKey, machineName=currSysplex[2]) OSHVResult.add(lparOSH) snmpOSH.setContainer(lparOSH) OSHVResult.add(snmpOSH) # Create contained link between discovered IP and lpar OSHVResult.add( modeling.createLinkOSH( 'contained', lparOSH, modeling.createOshByCmdbIdString( ipClass, DISCOVERED_IP_ID))) # Create member link between lpar and Mainframe OSHVResult.add( modeling.createLinkOSH('member', mainframeOSH, lparOSH)) # Create sysplex sysplexOSH = ObjectStateHolder('sysplex') sysplexOSH.setAttribute('data_name', currSysplex[1]) OSHVResult.add(sysplexOSH) # Create member link between lpar and sysplex OSHVResult.add( modeling.createLinkOSH('member', sysplexOSH, lparOSH)) # Create member link between mainframe and sysplex OSHVResult.add( modeling.createLinkOSH('member', mainframeOSH, sysplexOSH)) # connect all ips to lpar for currLparIp in lparIpList: if netutils.isLocalIp(currLparIp[1]): continue currIpOSH = modeling.createIpOSH(currLparIp[1]) OSHVResult.add(currIpOSH) OSHVResult.add( modeling.createLinkOSH('contained', lparOSH, currIpOSH)) break else: logger.debug("Failed to get Mainframe key.") else: errormessages.resolveAndReport( "Could not perform snmp connection to %s" % DISCOVERED_IP, ClientsConsts.SNMP_PROTOCOL_NAME, Framework) return OSHVResult
#coding=utf-8 import logger import modeling import netutils import ip_addr from appilog.common.system.types import AttributeStateHolder from appilog.common.system.types.vectors import StringVector _CMDB = modeling.CmdbClassModel() class InvalidIpException(Exception): def __init__(self, ip): self.ip = ip def __str__(self): return "IP address '%s' is invalid" % self.ip class InvalidNetmaskException(Exception): def __init__(self, netmask): self.netmask = netmask def __str__(self): return "Network mask '%s' is invalid" % self.netmask class Interface: def __init__(self, mac=None, name=None,
def DiscoveryMain(Framework): OSHVResult = ObjectStateHolderVector() ObjSHV = ObjectStateHolderVector() discInst = RunInstance() ipAddressList = Framework.getTriggerCIDataAsList('ip_address') credentialsList = Framework.getTriggerCIDataAsList('credentialsId') bridgeId = Framework.getDestinationAttribute('bridgeId') hostIdList = Framework.getTriggerCIDataAsList('hostId') ucmdbVersion = modeling.CmdbClassModel().version() snmpCommunityPostfix = '' try: snmpCommunityPostfix = Framework.getDestinationAttribute( 'snmpCommunityPostfix') hostModel = Framework.getDestinationAttribute('hostModel') hostOs = Framework.getDestinationAttribute('hostOs') snmpDescription = Framework.getDestinationAttribute('smpDescription') except: pass SwitchesNumber = len(credentialsList) for i in range(SwitchesNumber): ipAddress = ipAddressList[i] hostId = hostIdList[i] credId = credentialsList[i] properties = Properties() if credId and ipAddress: properties.setProperty('ip_address', ipAddress) properties.setProperty(BaseClient.CREDENTIALS_ID, credId) sw = Switch(bridgeId, hostId, ucmdbVersion, Framework) if (snmpCommunityPostfix != None) and (snmpCommunityPostfix != ''): device_type_str = '%s%s%s' % (hostModel.lower(), hostOs.lower(), snmpDescription.lower()) if device_type_str.find('atalyst') != -1 or device_type_str.find( 'cisco') != -1: snmp_version = Framework.getProtocolProperty( credId, "snmpprotocol_version") if snmp_version == 'version 3': props = Properties() props.setProperty('ip_address', ipAddress) props.setProperty(BaseClient.CREDENTIALS_ID, credId) client = Framework.createClient(props) vlan_context_dict = snmputils.get_snmp_vlan_context_dict( client) client and client.close() if not vlan_context_dict: raise Exception, "Vlan Conext is not present on the device. No Vlan details might be discovered" vlan_context = vlan_context_dict.get(snmpCommunityPostfix) if not vlan_context: raise Exception, "Failed to find configured Vlan context for Vlan %s. Vlan will be skipped" % snmpCommunityPostfix properties.setProperty(SnmpQueries._postfix, '%s' % vlan_context) else: properties.setProperty(SnmpQueries._postfix, '@%s' % snmpCommunityPostfix) else: sw = QBridgeSwitch(snmpCommunityPostfix, bridgeId, hostId, ucmdbVersion, Framework) sw.set_device_type_str(device_type_str) if logger.isDebugEnabled(): logger.debug('ip', ipAddress) logger.debug('bridgeMac', bridgeId) logger.debug('Postfix', snmpCommunityPostfix) try: sw.snmpClient = Framework.createClient(properties) #SnmpConnectionTester(sw.snmpClient).testSnmpConnection() sw.doWork(ObjSHV, discInst) OSHVResult.addAll(ObjSHV) except: logger.debugException('') if (snmpCommunityPostfix != None) and (snmpCommunityPostfix != ''): logger.error('Failed to discover ip: ', ipAddress, ' on Vlan#: ', snmpCommunityPostfix) else: logger.error('Failed to discover ip: ', ipAddress) if sw.snmpClient != None: sw.snmpClient.close() return OSHVResult