d786247c64a5fffdfcdb88c933cd44bddd317858
[appc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.appc.sdc.listener;
24
25 import com.att.eelf.configuration.EELFLogger;
26 import com.att.eelf.configuration.EELFManager;
27 import org.onap.appc.configuration.Configuration;
28 import org.onap.appc.configuration.ConfigurationFactory;
29 import org.onap.sdc.api.IDistributionClient;
30 import org.onap.sdc.api.results.IDistributionClientResult;
31 import org.onap.sdc.impl.DistributionClientFactory;
32 import org.onap.sdc.utils.DistributionActionResultEnum;
33
34 import java.net.URL;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.Properties;
38 import java.util.concurrent.CountDownLatch;
39 import java.util.concurrent.TimeUnit;
40
41 /**
42  * SDC listener handles bundle start and stop through start and stop method. <p>
43  * Register connection with SDC server based on properties file configuration when start,
44  * and disconnect with SDC server when stop.
45  */
46 public class SdcListener {
47     private final EELFLogger logger = EELFManager.getInstance().getLogger(SdcListener.class);
48
49     /**
50      * The bundle context
51      */
52     private IDistributionClient client;
53     private SdcCallback callback;
54     private SdcConfig config;
55     private CountDownLatch latch;
56
57     private Thread startThread = null;
58
59     @SuppressWarnings("unused")
60     public void start() throws Exception {
61         // Add timestamp to the log to differentiate the jmeter run testing calls.
62         final long timeStamp = System.currentTimeMillis();
63         logger.info(String.format("[%d] Starting SDC Listener", timeStamp));
64
65         Configuration configuration = ConfigurationFactory.getConfiguration();
66         Properties props = configuration.getProperties();
67         config = new SdcConfig(props);
68         logger.debug(String.format("[%d] created SDC config", timeStamp));
69
70         client = DistributionClientFactory.createDistributionClient();
71         logger.debug(String.format("[%d] created SDC client", timeStamp));
72
73         callback = new SdcCallback(config.getStoreOpURI(), client);
74         logger.debug(String.format("[%d] created SDC callback", timeStamp));
75
76         latch = new CountDownLatch(1);
77
78         startThread = new Thread(new StartRunnable(timeStamp));
79         startThread.setName(String.format("[%d] sdcListener start", timeStamp));
80         logger.debug(String.format("[%d] created SDC initialization thread", timeStamp));
81         startThread.start();
82     }
83
84     @SuppressWarnings("unused")
85     public void stop() throws InterruptedException {
86         // Add timestamp to the log to differentiate the jmeter run testing calls.
87         final long timeStamp = System.currentTimeMillis();
88         logger.info(String.format("[%d] Stopping SDC Listener", timeStamp));
89
90         stopStartThread(timeStamp);
91
92         if (latch != null) {
93             logger.debug(String.format("[%d] waiting SDC latch count to 0 for 10 seconds", timeStamp));
94             latch.await(10, TimeUnit.SECONDS);
95             latch = null;
96         }
97
98         if (callback != null) {
99             logger.debug(String.format("[%d] stopping SDC callback", timeStamp));
100             callback.stop();
101             callback = null;
102         }
103         if (client != null) {
104             logger.debug(String.format("[%d] stopping SDC client", timeStamp));
105             client.stop();
106             client = null;
107
108         }
109         logger.info(String.format("[%d] SDC Listener stopped successfully", timeStamp));
110     }
111
112     void stopStartThread(long timeStamp) throws InterruptedException {
113         if (startThread == null) {
114             return;
115         }
116
117         if (startThread.getState() == Thread.State.TERMINATED) {
118             logger.debug(String.format("[%d] SDC thread(%s) is already terminated.",
119                     timeStamp, startThread.getName()));
120         } else {
121             logger.debug(String.format("[%d] SDC thread(%s) is to be interrupted with state(%s)",
122                     timeStamp, startThread.getName(), startThread.getState().toString()));
123
124             startThread.interrupt();
125
126             logger.debug(String.format("[%d] SDC thread(%s) has been interrupted(%s) with state(%s)",
127                     timeStamp, startThread.getName(), startThread.isInterrupted(),
128                     startThread.getState().toString()));
129         }
130         startThread = null;
131     }
132
133     /**
134      * Runnable implementation for actual initialization during SDC listener start
135      */
136     class StartRunnable implements Runnable {
137         private final long timeStamp;
138
139         StartRunnable(long theTimeStamp) {
140             timeStamp = theTimeStamp;
141         }
142
143         /**
144          * This run method calls SDC client for init and start which are synchronized calls along with stop.
145          * To interrupt this thread at stop time, we added thread interrupted checking in each step
146          * for earlier interruption.
147          */
148         @Override
149         public void run() {
150             if (!initialRegistration()) {
151                 logger.warn(String.format("[%d] SDC thread initial registration failed.", timeStamp));
152             }
153
154             if (isThreadInterrupted("after initial registration")) {
155                 return;
156             }
157
158             IDistributionClientResult result = client.init(config, callback);
159
160             if (isThreadInterrupted("after client init")) {
161                 return;
162             }
163
164             if (result.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) {
165                 client.start();
166             } else {
167                 logger.error(String.format("[%d] Could not register SDC client. %s - %s",
168                         timeStamp, result.getDistributionActionResult(), result.getDistributionMessageResult()));
169             }
170
171             latch.countDown();
172         }
173
174         private boolean initialRegistration() {
175             try {
176                 final String jsonTemplate =
177                         "{\"consumerName\": \"%s\",\"consumerSalt\": \"%s\",\"consumerPassword\":\"%s\"}";
178                 String saltedPassStr = org.onap.tlv.sdc.security.Passwords.hashPassword(config.getPassword());
179                 if (saltedPassStr == null || !saltedPassStr.contains(":")) {
180                     return false;
181                 }
182
183                 String[] saltedPass = saltedPassStr.split(":");
184                 String json = String.format(jsonTemplate, config.getUser(), saltedPass[0], saltedPass[1]);
185
186                 Map<String, String> headers = new HashMap<>();
187                 // TODO - Replace the header below to sdc's requirements. What should the new value be
188                 headers.put("USER_ID", "test");
189
190                 // TODO - How to format the url. Always same endpoint or ports?
191                 String host = config.getAsdcAddress();
192                 URL url = new URL(String.format("http%s://%s/sdc2/rest/v1/consumers",
193                         host.contains("443") ? "s" : "", host));
194
195                 logger.info(String.format("Attempting to register user %s on %s with salted pass of %s",
196                         config.getUser(), url, saltedPass[1]));
197
198                 ProviderOperations providerOperations = new ProviderOperations();
199                 ProviderResponse result = providerOperations.post(url, json, headers);
200                 return result.getStatus() == 200;
201             } catch (Exception e) {
202                 logger.error(
203                         "Error performing initial registration with SDC server. User may not be able to connect",
204                         e);
205                 return false;
206             }
207         }
208
209         private boolean isThreadInterrupted(String details) {
210             if (Thread.currentThread().isInterrupted()) {
211                 logger.info(String.format("[%d] SDC thread interrupted %s.", timeStamp, details));
212                 return true;
213             }
214             return false;
215         }
216     }
217 }