2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Modifications copyright (c) 2018 AT&T Intellectual Property
21 package org.onap.vnf.health.read;
23 import org.onap.vnf.health.CrudService;
24 import org.onap.vnf.health.RESTManager;
25 import org.onap.vnf.health.RESTManager.Pair;
26 import org.onap.vnf.vlb.write.DnsInstanceManager;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vlb.business.vnf.onap.plugin.rev160918.vlb.business.vnf.onap.plugin.params.vdns.instances.VdnsInstance;
30 import io.fd.honeycomb.translate.read.ReadContext;
31 import io.fd.honeycomb.translate.read.ReadFailedException;
32 import io.fd.honeycomb.translate.spi.read.Initialized;
33 import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
35 import java.io.BufferedReader;
36 import java.io.FileInputStream;
37 import java.io.FileReader;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.text.SimpleDateFormat;
41 import java.util.ArrayList;
42 import java.util.Date;
43 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.List;
47 import java.util.Properties;
49 import javax.annotation.Nonnull;
51 import org.onap.vnf.health.CrudService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.HealthVnfOnapPluginStateBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.HealthCheckBuilder;
54 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;
55 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;
56 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;
57 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;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.health.vnf.onap.plugin.rev160918.health.vnf.onap.plugin.params.HealthCheck;
59 import org.opendaylight.yangtools.concepts.Builder;
60 import org.opendaylight.yangtools.yang.binding.DataObject;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
68 * Reader for {@link Element} list node from our YANG model.
70 public final class ElementStateCustomizer implements InitializingReaderCustomizer<HealthCheck, HealthCheckBuilder> {
72 private final CrudService<HealthCheck> crudService;
73 private DnsInstanceManager dnsInstanceManager;
74 private static final Logger LOG = LoggerFactory.getLogger(ElementStateCustomizer.class);
75 private final String SCRIPT;
76 private final String OUTPUT;
77 private final String VNFC;
78 private final Boolean PRIMARY;
79 private static SimpleDateFormat SDF;
80 private String vPktGenIp;
82 public ElementStateCustomizer(final CrudService<HealthCheck> crudService) throws IOException {
83 this.crudService = crudService;
84 dnsInstanceManager = DnsInstanceManager.getInstance();
86 // initialize data format
87 SDF = new SimpleDateFormat("MM-dd-yyyy:HH.mm.ss");
89 // read properties from file
90 String path = "/opt/config/properties.conf";
91 Properties prop = new Properties();
92 InputStream prop_file = new FileInputStream(path);
94 SCRIPT = prop.getProperty("script");
95 OUTPUT = prop.getProperty("output");
96 VNFC = prop.getProperty("vnfc");
97 PRIMARY = Boolean.parseBoolean(prop.getProperty("primary"));
101 vPktGenIp = readFromFile("/opt/config/oam_vpktgen_ip.txt");
106 public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final HealthCheck readData) {
107 // merge children data to parent builder
108 // used by infrastructure to merge data loaded in separated customizers
109 ((HealthVnfOnapPluginStateBuilder) builder).setHealthCheck(readData);
114 public HealthCheckBuilder getBuilder(@Nonnull final InstanceIdentifier<HealthCheck> id) {
115 // return new builder for this data node
116 return new HealthCheckBuilder();
120 public void readCurrentAttributes(@Nonnull final InstanceIdentifier<HealthCheck> id,
121 @Nonnull final HealthCheckBuilder builder,
122 @Nonnull final ReadContext ctx) throws ReadFailedException {
124 // assess the health status of the local service (try at most three times, otherwise return an error).
126 String [] cmdArgs = {"/bin/bash", "-c", SCRIPT};
132 Process child = Runtime.getRuntime().exec(cmdArgs);
133 // wait for child process to terminate
134 ret = child.waitFor();
137 catch (IOException e) {
138 LOG.error("Command: [" + SCRIPT + "] returned an error.");
141 catch (InterruptedException e) {
142 LOG.error("Child process: [" + SCRIPT + "] returned an error. Error code: " + ret);
145 } while(ret != 0 && attempts < 3);
148 healthStatus = readFromFile(OUTPUT);
149 if(healthStatus == null) {
150 healthStatus = "unhealthy";
152 LOG.info("Assessing the health status of the local component... Return status = \"" + healthStatus + "\"");
155 healthStatus = "unhealthy";
156 LOG.info("Failed to assess the health status of the local component. Return status = \"unhealthy\"");
159 // check the status of other VNF components, if any
161 // check the vPacketGenerator first
162 if(vPktGenIp != null) {
163 if(!getRemoteVnfcHealthStatus(vPktGenIp)) {
164 healthStatus = "unhealthy";
168 // check all the vDNS instances
169 Map<String, VdnsInstance> activeVdnsInstances = dnsInstanceManager.getDnsInstancesAsMap();
170 Iterator<String> iter = activeVdnsInstances.keySet().iterator();
171 while(iter.hasNext()){
172 if(!getRemoteVnfcHealthStatus(activeVdnsInstances.get(iter.next()).getOamIpAddr())) {
173 healthStatus = "unhealthy";
178 // and sets it to builder
179 builder.setState(healthStatus);
180 builder.setVnfName(VNFC);
181 builder.setTime(SDF.format(new Date().getTime()));
183 if(healthStatus.equals("unhealthy")) {
184 List<Fault> faultList = new ArrayList<Fault>();
185 // build a FaultBuilder object in case of one or more VNF components are reporting faults
186 FaultBuilder faultBuilder = new FaultBuilder();
187 faultBuilder.setVnfComponent(VNFC);
188 faultBuilder.setMessage("The VNF is not running correctly");
189 faultBuilder.setKey(new FaultKey(faultBuilder.getVnfComponent()));
190 faultList.add(faultBuilder.build());
192 // build a FaultsBuilder object that contains a list of Fault instances
193 FaultsBuilder faultsBuilder = new FaultsBuilder();
194 faultsBuilder.setInfo("One or more VNF components are unreachable");
195 faultsBuilder.setFault(faultList);
197 // add the Faults object to HealthCheckBuilder
198 builder.setFaults(faultsBuilder.build());
201 // create the final HealthCheck object
206 * Initialize configuration data based on operational data.
208 * Very useful when a plugin is initiated but the underlying layer already contains some operation state.
209 * Deriving the configuration from existing operational state enables reconciliation in case when
210 * Honeycomb's persistence is not available to do the work for us.
214 public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<HealthCheck> id,
215 @Nonnull final HealthCheck readValue,
216 @Nonnull final ReadContext ctx) {
217 return Initialized.create(id, readValue);
220 private String readFromFile(String path) {
221 // auto close the file reader
222 try (BufferedReader br = new BufferedReader(new FileReader(path))) {
224 while ((line = br.readLine()) != null) {
227 } catch (IOException e) {
233 private boolean getRemoteVnfcHealthStatus(String ipAddr) {
234 // set up the REST manager
235 RESTManager mgr = new RESTManager();
236 Map<String, String> headers = new HashMap<String, String>();
237 headers.put("Content-Type", "application/json");
238 headers.put("Accept", "application/json");
240 // execute the request
241 String URI = "http://" + ipAddr + ":8183/restconf/operational/health-vnf-onap-plugin:health-vnf-onap-plugin-state/health-check";
242 Pair<Integer, String> result = mgr.get(URI, "admin", "admin", headers);
244 return (!result.b.contains("unhealthy"));