summaryrefslogtreecommitdiffstats
path: root/src/site-docs/adoc/fragments/howto-websockets/demo-05-send-events.adoc
blob: 3f5955869e3944e2afdd28b907c208dc02af0921 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//
// ============LICENSE_START=======================================================
//  Copyright (C) 2016-2018 Ericsson. All rights reserved.
// ================================================================================
// This file is licensed under the CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL LICENSE
// Full license text at https://creativecommons.org/licenses/by/4.0/legalcode
// 
// SPDX-License-Identifier: CC-BY-4.0
// ============LICENSE_END=========================================================
//
// @author Sven van der Meer (sven.van.der.meer@ericsson.com)
//

=== Send Events

Now you have the full system up and running:

- Terminal 1: APEX ready and loaded
- Terminal 2: an echo client, printing received messages produced by the VPN policy
- Terminal 2: a console client, waiting for input on the console (standard in) and sending text to APEX

We started the engine with the VPN policy example.
So all the events we are using now are located in files in the following example directory:

[source%nowrap,sh,numbered]
----
#: $APEX_HOME/examples/events/VPN
> %APEX_HOME%\examples\events\VPN
----

To sends events, simply copy the content of the event files into Terminal 3 (the console client).
It will read multi-line JSON text and send the events.
So copy the content of `SetupEvents.json` into the client.
APEX will trigger a policy and produce some output, the echo client will also print some events created in the policy.
In Terminal 1 (APEX) you’ll see some status messages from the policy as:

[source%nowrap,sh,numbered,subs="attributes+"]
----
include::{adsite-main-dir}/site-docs/adoc/fragments/howto-websockets/wsc-screens/vpn-setup-events.log[APEX output for VPN Setup Events]
----

In Terminal 2 (echo-client) you see the received events, the last two should look like:

[source%nowrap,sh,numbered,subs="attributes+"]
----
include::{adsite-main-dir}/site-docs/adoc/fragments/howto-websockets/wsc-screens/echo-client-received-events.log[Echo Client Received Events]
----

Congratulations, you have triggered a policy in APEX using Websockets, the policy did run through, created events, picked up by the echo-client.

Now you can send the Link 09 and Link 10 events, they will trigger the actual VPN policy and some calculations are made.
Let’s take the Link 09 events from `Link09Events.json`, copy them all into Terminal 3 (the console).
APEX will run the policy (with some status output), and the echo client will receive and print events.

To terminate the applications, simply press `CTRL+C` in Terminal 1 (APEX).
This will also terminate the echo-client in Terminal 2.
Then type `exit<enter>` in Terminal 3 (or `CTRL+C`) to terminate the console-client.
old } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*-
 * ============LICENSE_START=======================================================
 * OPENECOMP - MSO
 * ================================================================================
 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 * ================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============LICENSE_END=========================================================
 */

package org.openecomp.mso;


import org.openecomp.mso.db.catalog.CatalogDatabase;
import org.openecomp.mso.logger.MessageEnum;
import org.openecomp.mso.logger.MsoLogger;
import org.openecomp.mso.properties.MsoJavaProperties;
import org.openecomp.mso.properties.MsoJsonProperties;
import org.openecomp.mso.properties.MsoPropertiesFactory;
import org.openecomp.mso.requestsdb.RequestsDatabase;
import org.openecomp.mso.utils.UUIDChecker;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import javax.ws.rs.core.Response;

public class HealthCheckUtils {

    private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL);
    private final static String MSO_PROP_TOPOLOGY = "MSO_PROP_TOPOLOGY";
    private static MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
    private static final String CHECK_HTML = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Health Check</title></head><body>Application ready</body></html>";
    private static final String NOT_FOUND = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Application Not Started</title></head><body>Application not started. Properties file missing or invalid or database Connection failed</body></html>";
    private static final String NOT_HEALTHY = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Application Not Started</title></head><body>Application not available or at least one of the sub-modules is not available.</body></html>";
    public static final Response HEALTH_CHECK_RESPONSE = Response.status (HttpStatus.SC_OK)
            .entity (CHECK_HTML)
            .build ();
    public static final Response HEALTH_CHECK_NOK_RESPONSE = Response.status (HttpStatus.SC_SERVICE_UNAVAILABLE)
            .entity (NOT_HEALTHY)
            .  build ();
    public static final Response NOT_STARTED_RESPONSE = Response.status (HttpStatus.SC_SERVICE_UNAVAILABLE)
            .entity (NOT_FOUND)
            .build ();

    public enum NodeType {APIH, RA};

    public boolean catalogDBCheck (MsoLogger subMsoLogger, long startTime) {
        try (CatalogDatabase catalogDB = new CatalogDatabase ()) {
            catalogDB.healthCheck ();
        } catch (Exception e) {
            subMsoLogger.error(MessageEnum.GENERAL_EXCEPTION, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Failed to check catalog database", e);
            subMsoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Exception during healthcheck");
            return false;
        }
        return true;
    }

    public boolean requestDBCheck (MsoLogger subMsoLogger, long startTime) {
        try {
            RequestsDatabase.healthCheck ();
        } catch (Exception e) {
            subMsoLogger.error(MessageEnum.GENERAL_EXCEPTION, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Failed to check request database", e);
            subMsoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.ServiceNotAvailable, "Exception during local healthcheck");
            return false;
        }
        return true;
    }

    public boolean siteStatusCheck (MsoLogger subMsoLogger, long startTime) {
        // Check the Site Status value in DB first, if set to false, return NOK
        String site = getProperty("site-name");

        MsoStatusUtil statusUtil = new MsoStatusUtil ();
        if (!statusUtil.getSiteStatus (site)) {
            subMsoLogger.debug("This site is currently disabled for maintenance.");
            return false;
        }
        return true;
    }

    public boolean configFileCheck (MsoLogger subMsoLogger, long startTime, String propertiesFile) {
        if (null != propertiesFile) {
            MsoJavaProperties props = loadMsoProperties (propertiesFile);
            if (props == null) {
                subMsoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.ServiceNotAvailable, "Configuration file can not be loaded");
                return false;
            }
        }
        return true;
    }


    private MsoJavaProperties loadMsoProperties (String fileName) {
        MsoJavaProperties msoProperties;
        try {
            msoProperties = msoPropertiesFactory.getMsoJavaProperties(fileName);
        } catch (Exception e) {
            msoLogger.error (MessageEnum.LOAD_PROPERTIES_FAIL, fileName, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Failed to load topology properties", e);
            return null;
        }
        if (msoProperties !=null && msoProperties.size() > 0) {
            return msoProperties;
        } else {
            msoLogger.error (MessageEnum.NO_PROPERTIES, fileName, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "No topology properties");
            return  null;
        }
    }

    protected boolean verifyLocalHealth(String ip, String apiPort, String url, String sslEnabled, String requestId) {
        String finalUrl = getFinalUrl(ip, apiPort, url, sslEnabled);
        long startTime = System.currentTimeMillis ();
        if (null != requestId) {
            finalUrl = finalUrl + "?requestId=" + requestId;
        }
        try (CloseableHttpClient client = getHttpClient()) {
            HttpResponse response;
            HttpGet get = new HttpGet(finalUrl);
            msoLogger.debug("Get url is: " + finalUrl);
            response = client.execute(get);
            msoLogger.debug("Get response is: " + response);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                msoLogger.debug("verifyLocalHealth - Successfully communicate with APIH/BPMN/RA");
                return true;
            }
            msoLogger.debug("verifyLocalHealth - Service not available");
        } catch (Exception e) {
            msoLogger.error(MessageEnum.GENERAL_EXCEPTION, "", "HealthCheck", MsoLogger.ErrorCode.UnknownError, "Error in local HealthCheck", e);
            msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with APIH/BPMN/RA", url, "HealthCheck", null);
            msoLogger.debug("Exception while triggering local health check api:" + finalUrl);
        }
        return false;
    }

    protected CloseableHttpClient getHttpClient () {
        // set the connection timeout value to 30 seconds (30000 milliseconds)
        RequestConfig.Builder requestBuilder = RequestConfig.custom();
        requestBuilder = requestBuilder.setConnectTimeout(30000);
        requestBuilder = requestBuilder.setConnectionRequestTimeout(30000);
        HttpClientBuilder builder = HttpClientBuilder.create ();
        builder.setDefaultRequestConfig (requestBuilder.build ());

        return builder.build ();
    }

    public MsoJavaProperties loadTopologyProperties() {
        MsoJavaProperties msoProperties;
        try {
            msoProperties = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_TOPOLOGY);
        } catch (Exception e) {
            msoLogger.error(MessageEnum.LOAD_PROPERTIES_FAIL, MSO_PROP_TOPOLOGY, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Not able to load topology properties", e);
            return null;
        }

        if (msoProperties != null && msoProperties.size() > 0) {
            return msoProperties;
        } else {
            msoLogger.error(MessageEnum.LOAD_PROPERTIES_FAIL, MSO_PROP_TOPOLOGY, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Not able to load topology properties");
            return null;
        }
    }

    public boolean verifyNodeHealthCheck (HealthCheckUtils.NodeType type, String requestId) {
        // Get info from topology properties file
        MsoJavaProperties topologyProp = this.loadTopologyProperties();
        if (null == topologyProp) {
            return false;
        }
        String port = topologyProp.getProperty("server-port", null);
        String ip = System.getProperty("jboss.qualified.host.name");
        String sslEnabled = topologyProp.getProperty("ssl-enable", null);

        if (null == port || null == ip || ip.isEmpty() || port.isEmpty()) {
            msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Not able to get the IP or the Port value. IP:" + ip + "; Port:" + port, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Not able to get the IP or the Port value. IP:" + ip + "; Port:" + port);
            return false;
        }

        String[] apis;
        if (NodeType.APIH.equals (type)) {
            String apiList = topologyProp.getProperty("apih-healthcheck-urn", null);
            if (null == apiList) {
                msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Not able to get apih-healthcheck-urn parameter", "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Not able to get apih-healthcheck-urn parameter");
                return false;
            }
            apis = apiList.split(",");
        } else if (NodeType.RA.equals (type)){
            String apiList = topologyProp.getProperty("jra-healthcheck-urn", null);
            if (null == apiList) {
                msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Not able to get jra-healthcheck-urn parameter", "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Not able to get jra-healthcheck-urn parameter");
                return false;
            }
            apis = apiList.split(",");
        } else {
            msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Unknown NodeType:" + type, "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Unknown NodeType:" + type);
            return false;
        }

        // Verify health check on APIH servers
        for (String url : apis) {
            // if any of the parameters is null or empty, no need to establish the health check request, just go to the next iteration
            if ((url == null)  || url.isEmpty()) {
                continue;
            }
            // Exit the loop if local health check returns false from any of the sub component
            if (!this.verifyLocalHealth(ip, port, url, sslEnabled, requestId)) {
                return false;
            }
        }
        return true;
    }

    public boolean verifyGlobalHealthCheck(boolean verifyBpmn, String requestId) {
        // Get info from topology properties file
        MsoJavaProperties topologyProp = this.loadTopologyProperties();
        if (null == topologyProp) {
            msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Not able to find the topology file", "", "HealthCheck", MsoLogger.ErrorCode.PermissionError, "Not able to find the topology file");
            return false;
        }

        String apihLB = topologyProp.getProperty("apih-load-balancer", null);
        String apihApi = topologyProp.getProperty("apih-nodehealthcheck-urn", null);
        String bpmnLB= topologyProp.getProperty("camunda-load-balancer", null);
        String bpmnApi = topologyProp.getProperty("camunda-healthcheck-urn", null);
        String jraLB = topologyProp.getProperty("jra-load-balancer", null);
        String jraApi = topologyProp.getProperty("jra-nodehealthcheck-urn", null);

        if (null == apihLB || null == apihApi || null == bpmnLB || null == bpmnApi || null == jraLB || null == jraApi
                || apihLB.isEmpty () || apihApi.isEmpty () || bpmnLB.isEmpty () || bpmnApi.isEmpty () || jraLB.isEmpty () || jraApi.isEmpty () ) {
            msoLogger.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Key parameters are missing from the topology file", "", "HealthCheck", MsoLogger.ErrorCode.DataError, "Key parameters are missing from the topology file");
            return false;
        }

        // Verify health check on APIH servers
        if (!this.verifyLocalHealth (apihLB, null, apihApi, null, requestId)) {
            return false;
        }

        // Verify health check on Camunda servers
        if (verifyBpmn) {
            if (!this.verifyLocalHealth (bpmnLB, null, bpmnApi, null, requestId)) {
                return false;
            }
        }

        // Verify health check on RA servers
        if (!verifyLocalHealth (jraLB, null, jraApi, null, requestId)) {
            return false;
        }

        return true;
    }

    public String getProperty (String name) {
        MsoJavaProperties prop = this.loadTopologyProperties();

        return prop.getProperty(name, null);
    }

    protected String getFinalUrl (String ip, String port, String url, String sslEnabled) {
        if (null == port && null == sslEnabled) {
            int length = ip.length();
            if (ip.substring(length - 1).equals ("/")) {
                ip = ip.substring (0, length - 1);
            }
            return ip + url;
        } else if (null != sslEnabled && "true".equals (sslEnabled.toLowerCase ())) {
            return "https://" + ip + ":" + port + url;
        } else {
            return "http://" + ip + ":" + port + url;
        }
    }
}