/************************************************************ * * * Contents of file Copyright (c) Moogsoft Inc 2019 * * * * Unapproved changes to the code are unsupported. * * Submit any changes to Moogsoft for review. * * * ************************************************************/ import com.hp.opr.api.ws.adapter.BulkReceiveChangeArgs import com.hp.opr.api.ws.model.event.OprEvent import com.hp.opr.api.ws.model.event.OprEventChange import com.hp.opr.api.ws.model.event.OprEventList import com.hp.opr.api.ws.model.event.OprGroup import com.hp.opr.api.ws.model.event.OprPriority import com.hp.opr.api.ws.model.event.OprSeverity import com.hp.opr.api.ws.model.event.OprState import com.hp.opr.api.ws.model.event.OprUser import com.hp.opr.api.ws.model.event.ci.OprConfigurationItem import com.hp.opr.api.ws.model.event.ci.OprForwardingInfo import com.hp.opr.common.model.NodeInfo import com.hp.opr.common.util.BsmEnvironment import com.hp.opr.eventsync.ws.client.WinkClientSupport import groovy.util.slurpersupport.GPathResult import groovy.xml.MarkupBuilder import java.net.PasswordAuthentication import java.security.cert.X509Certificate import java.util.Set import javax.ws.rs.core.Cookie import javax.ws.rs.core.MediaType import javax.ws.rs.core.MultivaluedMap import javax.xml.bind.JAXBContext import javax.xml.bind.JAXBException import javax.xml.bind.Marshaller import org.apache.wink.client.ClientRequest import org.apache.wink.client.ClientResponse import org.apache.wink.client.ClientWebException import org.apache.wink.client.Resource import org.apache.wink.client.RestClient class CHpomiPushAdapter { static def ROOT_DRILLDOWN_PATH = "/opr-console/opr-evt-details.jsp?eventId=" def mLogfileDir = null def mLogger = null def mConnectedServerId = null def mConnectedServerName = null def mConnectedServerDisplayName = null def mConnectedServerCertificate = null def mTimeout = null def mClient = null def mLocalhostInfo = null def mResource = null def mProtocol = 'http' def mNode = 'localhost' def mPort = 48015 def mMarsh = null def init(def args) { mLogger = args.logger mLogger.info("Moogsoft push adapter initalized. INSTALL_DIR=${args.installDir}") mConnectedServerId = args.connectedServerId mConnectedServerName = args.connectedServerName mConnectedServerDisplayName = args.connectedServerDisplayName mConnectedServerCertificate = args.connectedServerCertificate mTimeout = args.maxTimeout == null ? 60 : args.maxTimeout mProtocol = args.nodeSsl ? 'https' : 'http' mNode = args.node mPort = (args.port == null || args.port < 1) ? (args.nodeSsl ? 48015 : 48015) : args.port mClient = WinkClientSupport.getRestClient(mTimeout, mConnectedServerCertificate) JAXBContext context = JAXBContext.newInstance(OprEvent.class) mMarsh = context.createMarshaller() //for pretty-print XML in JAXB mMarsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE) def timestamp = new Date() def msg = """\n\n### ${timestamp.toString()}: init() called ### parameter connected server ID: ${mConnectedServerId} parameter connected server name: ${mConnectedServerName} parameter connected server display name: ${mConnectedServerDisplayName} parameter node: ${mNode} parameter port: ${mPort} parameter ssl: ${args.nodeSsl} parameter drilldown node: ${args.drilldownNode} parameter drilldown port: ${args.drilldownPort} parameter drilldown ssl: ${args.drilldownNodeSsl}""" mLogger.info(msg) } def destroy() { mLogger.info("Moogsoft push adapter destroy.") } def ping(def args) { args.outputDetail = "Success." return true } def forwardEvent(def args) { mLogger.info("\nMoogsoft push adapter's forwardEvent() called.") args.externalRefId = logEvent(args.event, args.info, args.causeExternalRefId, args.credentials?.userName) // Make a drilldown base path to the original event as an example args.drilldownUrlPath = "${ROOT_DRILLDOWN_PATH}${args.event.getId()}" OprEvent event = args.event if(null == mResource) { // get the resource client connection to make the post mResource = createRequest(mProtocol, mNode, mPort, args.credentials) } def incident = jaxbObjectToXML(event) sendEventToExternalSystem(incident) return true } def logEvent(def event, def info, def causeExternalRefId, def userName) { def extId = "urn:uuid:${event.getId()}" def controlServerName = (event.controlTransferredTo) ? event.controlTransferredTo.name : "" def controlServerDnsName = (event.controlTransferredTo) ? event.controlTransferredTo.dnsName : "" def controlTransferredState = (event.controlTransferredTo) ? event.controlTransferredTo.state : "" def controlExternalId = (event.controlTransferredTo) ? event.controlTransferredTo.externalId : "" return extId } def forwardEvents(def args) { mLogger.info("\nMoogsoft push adapter's forwardEvents() called.") OprEventList events = args.events if(null == mResource) { // get the resource client connection to make the post mResource = createRequest(mProtocol, mNode, mPort, args.credentials) } mLogger.info("\n*** Begin Bulk Forward ***\n") for (OprEvent event in events.eventList) { def causeExternalRefId = getCauseExternalRefId(args, event) def externalRefId = logEvent(event, event.getForwardingInfo(mConnectedServerId), causeExternalRefId, args.credentials?.userName) // Make a drilldown base path to the original event as an example def drilldownUrlPath = "${ROOT_DRILLDOWN_PATH}${event.id}" args.setForwardSuccess(event.id, externalRefId, drilldownUrlPath) def incident = jaxbObjectToXML(event) sendEventToExternalSystem(incident) } mLogger.info("\n*** End Bulk Forward ***\n") return true } def getCauseExternalRefId(def args, def event) { String causeExternalRefId = "" if (event?.cause?.targetId) { OprEvent causeEvent = args.getEvent(event.cause.targetId, false) if (causeEvent) { OprForwardingInfo causeInfo = causeEvent.getForwardingInfo(mConnectedServerId) causeExternalRefId = causeInfo?.externalId } } return causeExternalRefId } def forwardChange(def args) { mLogger.info("\nMoogsoft push adapter's forwardChange() called.") OprEvent event = args.event if(null == mResource) { // get the resource client connection to make the post mResource = createRequest(mProtocol, mNode, mPort, args.credentials) } def incident = jaxbObjectToXML(event) sendEventToExternalSystem(incident) return true } def forwardChanges(def args) { mLogger.info("\nMoogsoft push adapter's forwardChanges() called.") if(null == mResource) { // get the resource client connection to make the post mResource = createRequest(mProtocol, mNode, mPort, args.credentials) } mLogger.debug("\n*** Begin Bulk Forward Change ***\n") for (OprEventChange change in args.changes.eventChanges) { def causeExternalRefId = getCauseExternalRefId(args, args.getEvent(change.eventRef.targetGlobalId, false)) args.setForwardSuccess(change.id) OprEvent event = args.getEvent(change.eventRef.targetGlobalId, false) def incident = jaxbObjectToXML(event) sendEventToExternalSystem(incident) } mLogger.info("\n*** End Bulk Forward Change ***\n") return true } def getExternalEvent(def args) { mLogger.info("\nMoogsoft push adapter's getExternalEvent() called.") args.assignedUser = "logger" args.assignedGroup = "logging group" args.state = "open" args.severity = "normal" args.priority = "none" return true } def receiveChange(def args) { // TODO: 5. Implement this to support SYNCHRONIZE, SYNCHRONIZE & TRANSFER COTRNOL // This method will receive & process the changes from the target server. return true; } Boolean receiveChanges(def args) { throw new UnsupportedOperationException("Bulk change receipt not supported by Moogsoft push adapter.") } def jaxbObjectToXML(def event) { try { // Write to XML String final StringWriter writter = new StringWriter() mMarsh.marshal(event, writter) return writter.toString() } catch (JAXBException e) { mLogger.error(e.printStackTrace()) } } def createRequest(def protocol, def node, def port, def credentials) { def address = "${protocol}://${mConnectedServerDisplayName}" mLogger.info("\nCreating request for: ${address}") // create the resource instance to interact with def resource = mClient.resource(address) // SM requires as media type application/json resource.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_XML) if (credentials != null) { // Set the username and password in the request. byte[] encodedUserPassword = Base64.getEncoder().encode((credentials.getUserName() + ":" + new String(credentials.getPassword())).getBytes()) resource.header("Authorization", "Basic " + new String(encodedUserPassword)) } return resource } def sendEventToExternalSystem(def incident) { def response if (mLogger.isDebugEnabled()) mLogger.debug("\nSending event data to Node: ${mNode}, Port: ${mPort}, XML in request:\n${incident}") else mLogger.info("\nSending event data to Node: ${mNode}, Port: ${mPort}") try { def clientResponse = mResource.post(incident) response = clientResponse.getEntity(String.class) if (response) { mLogger.info("\nResponse recieved from ${mNode}:${mPort} is : ${response}.") } else mLogger.info("\nNull response returned by server ${mNode}:${mPort}.") } catch (ClientWebException e) { def errMsg = """\nNode: ${mNode}, Port: ${mPort}, ClientWebException encountered: " + "(${e.getResponse()?.getStatusCode()}) ${e.getResponse()?.getMessage()}""" mLogger.error(errMsg) throw e } } }