From 2a759ffd2f6a4cd692fcc333ac87fd8921a5c936 Mon Sep 17 00:00:00 2001 From: Marco Platania Date: Fri, 16 Mar 2018 16:31:33 -0400 Subject: Add health check to vLBMS - Add health check to VNF components for vLB manual scale out - Update POM tree Change-Id: Id348d0cb56adf052694c6e8682b499eb1ac24af1 Issue-ID: INT-433 Signed-off-by: Marco Platania --- .../vnf/health/read/ElementStateCustomizer.java | 240 +++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java (limited to 'vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java') diff --git a/vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java b/vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java new file mode 100644 index 00000000..5486928d --- /dev/null +++ b/vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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. + */ + + /* + * Modifications copyright (c) 2018 AT&T Intellectual Property + */ + +package org.onap.vnf.health.read; + +import org.onap.vnf.health.CrudService; +import org.onap.vnf.health.RESTManager; +import org.onap.vnf.health.RESTManager.Pair; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.annotation.Nonnull; + +import org.onap.vnf.health.CrudService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.HealthVnfOnapPluginStateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.HealthCheckBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.health.check.FaultsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.health.check.faults.Fault; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.health.check.faults.FaultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.health.check.faults.FaultKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.HealthCheck; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Reader for {@link Element} list node from our YANG model. + */ +public final class ElementStateCustomizer implements InitializingReaderCustomizer { + + private final CrudService crudService; + private static final Logger LOG = LoggerFactory.getLogger(ElementStateCustomizer.class); + private final String SCRIPT; + private final String OUTPUT; + private final String VNFC; + private final Boolean PRIMARY; + private static SimpleDateFormat SDF; + + public ElementStateCustomizer(final CrudService crudService) throws IOException { + this.crudService = crudService; + + // initialize data format + SDF = new SimpleDateFormat("MM-dd-yyyy:HH.mm.ss"); + + // read properties from file + String path = "/opt/config/properties.conf"; + Properties prop = new Properties(); + InputStream prop_file = new FileInputStream(path); + prop.load(prop_file); + SCRIPT = prop.getProperty("script"); + OUTPUT = prop.getProperty("output"); + VNFC = prop.getProperty("vnfc"); + PRIMARY = Boolean.parseBoolean(prop.getProperty("primary")); + prop_file.close(); + } + + @Override + public void merge(@Nonnull final Builder builder, @Nonnull final HealthCheck readData) { + // merge children data to parent builder + // used by infrastructure to merge data loaded in separated customizers + ((HealthVnfOnapPluginStateBuilder) builder).setHealthCheck(readData); + } + + @Nonnull + @Override + public HealthCheckBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + // return new builder for this data node + return new HealthCheckBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final HealthCheckBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + List ipAddr = new ArrayList(); + if(PRIMARY) { + String ret = readFromFile("/opt/config/oam_vpktgen_ip.txt"); + if(ret != null) { + ipAddr.add(ret); + } + ret = readFromFile("/opt/config/oam_vdns_ip.txt"); + if(ret != null) { + ipAddr.add(ret); + } + } + + // assess the health status of the local service (try at most three times, otherwise return an error). + String healthStatus; + String [] cmdArgs = {"/bin/bash", "-c", SCRIPT}; + int ret = -1; + int attempts = 0; + + do { + try { + Process child = Runtime.getRuntime().exec(cmdArgs); + // wait for child process to terminate + ret = child.waitFor(); + attempts++; + } + catch (IOException e) { + LOG.error("Command: [" + SCRIPT + "] returned an error."); + e.printStackTrace(); + } + catch (InterruptedException e) { + LOG.error("Child process: [" + SCRIPT + "] returned an error. Error code: " + ret); + e.printStackTrace(); + } + } while(ret != 0 && attempts < 3); + + if(ret == 0) { + healthStatus = readFromFile(OUTPUT); + if(healthStatus == null) { + healthStatus = "unhealthy"; + } + LOG.info("Assessing the health status of the local component... Return status = \"" + healthStatus + "\""); + } + else { + healthStatus = "unhealthy"; + LOG.info("Failed to assess the health status of the local component. Return status = \"unhealthy\""); + } + + // perform read of details of data specified by key of Element in id + // final HealthCheck data = crudService.readSpecific(id); + + // check the status of other VNF components, if any + if(PRIMARY) { + for(int i = 0; i < ipAddr.size(); i++) { + if(!getRemoteVnfcHealthStatus(ipAddr.get(i))) { + healthStatus = "unhealthy"; + } + } + } + + // and sets it to builder + builder.setState(healthStatus); + builder.setVnfName(VNFC); + builder.setTime(SDF.format(new Date().getTime())); + + if(healthStatus.equals("unhealthy")) { + List faultList = new ArrayList(); + // build a FaultBuilder object in case of one or more VNF components are reporting faults + FaultBuilder faultBuilder = new FaultBuilder(); + faultBuilder.setVnfComponent(VNFC); + faultBuilder.setMessage("The VNF is not running correctly"); + faultBuilder.setKey(new FaultKey(faultBuilder.getVnfComponent())); + faultList.add(faultBuilder.build()); + + // build a FaultsBuilder object that contains a list of Fault instances + FaultsBuilder faultsBuilder = new FaultsBuilder(); + faultsBuilder.setInfo("One or more VNF components are unreachable"); + faultsBuilder.setFault(faultList); + + // add the Faults object to HealthCheckBuilder + builder.setFaults(faultsBuilder.build()); + } + + // create the final HealthCheck object + builder.build(); + } + /** + * + * Initialize configuration data based on operational data. + *

+ * Very useful when a plugin is initiated but the underlying layer already contains some operation state. + * Deriving the configuration from existing operational state enables reconciliation in case when + * Honeycomb's persistence is not available to do the work for us. + */ + @Nonnull + @Override + public Initialized init(@Nonnull final InstanceIdentifier id, + @Nonnull final HealthCheck readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(id, readValue); + } + + private String readFromFile(String path) { + // auto close the file reader + try (BufferedReader br = new BufferedReader(new FileReader(path))) { + String line; + while ((line = br.readLine()) != null) { + return line; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + private boolean getRemoteVnfcHealthStatus(String ipAddr) { + // set up the REST manager + RESTManager mgr = new RESTManager(); + Map headers = new HashMap(); + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + + // execute the request + String URI = "http://" + ipAddr + ":8183/restconf/operational/health-vnf-onap-plugin:health-vnf-onap-plugin-state/health-check"; + Pair result = mgr.get(URI, "admin", "admin", headers); + + return (!result.b.contains("unhealthy")); + } +} -- cgit 1.2.3-korg