aboutsummaryrefslogtreecommitdiffstats
path: root/vnfs/vLBMS/apis/health-vnf-onap-plugin/health-vnf-onap-plugin-impl/src/main/java/org/onap/vnf/health/read/ElementStateCustomizer.java
blob: 5486928db70df17de5b518bd91b5c70e1e4022a6 (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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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<HealthCheck, HealthCheckBuilder> {

    private final CrudService<HealthCheck> 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<HealthCheck> 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<? extends DataObject> 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<HealthCheck> id) {
        // return new builder for this data node
        return new HealthCheckBuilder();
    }

    @Override
    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<HealthCheck> id,
                                      @Nonnull final HealthCheckBuilder builder,
                                      @Nonnull final ReadContext ctx) throws ReadFailedException {

    	List<String> ipAddr = new ArrayList<String>();
    	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<Fault> faultList = new ArrayList<Fault>();
            // 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.
     * <p/>
     * 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<? extends DataObject> init(@Nonnull final InstanceIdentifier<HealthCheck> 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<String, String> headers = new HashMap<String, String>();
		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<Integer, String> result = mgr.get(URI, "admin", "admin", headers);

    	return (!result.b.contains("unhealthy"));
    }
}