fix dmaap-listener startup and library
[sdnc/northbound.git] / asdcApi / provider / src / main / java / org / openecomp / sdnc / asdcapi / AsdcApiProvider.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                                      reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.sdnc.asdcapi;
23
24 import com.google.common.base.Optional;
25 import com.google.common.util.concurrent.CheckedFuture;
26 import com.google.common.util.concurrent.Futures;
27 import java.util.Properties;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.ExecutorService;
30 import java.util.concurrent.Executors;
31 import java.util.concurrent.Future;
32 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
33 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
34 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
37 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
38 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
39 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
40 import org.opendaylight.yang.gen.v1.http.xmlns.openecomp.org.asdc.license.model._1._0.rev160427.vf.license.model.grouping.VfLicenseModel;
41 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.ASDCAPIService;
42 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.Artifacts;
43 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.ArtifactsBuilder;
44 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateInput;
45 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateInputBuilder;
46 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateOutput;
47 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateOutputBuilder;
48 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelVersions;
49 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelVersionsBuilder;
50 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.Artifact;
51 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.ArtifactBuilder;
52 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.ArtifactKey;
53 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.vf.license.model.versions.VfLicenseModelVersion;
54 import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.vf.license.model.versions.VfLicenseModelVersionBuilder;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 /**
62  * Defines a base implementation for your provider. This class extends from a helper class
63  * which provides storage for the most commonly used components of the MD-SAL. Additionally the
64  * base class provides some basic logging and initialization / clean up methods.
65  *
66  * To use this, copy and paste (overwrite) the following method into the TestApplicationProviderModule
67  * class which is auto generated under src/main/java in this project
68  * (created only once during first compilation):
69  *
70  * <pre>
71
72     @Override
73     public java.lang.AutoCloseable createInstance() {
74
75          final asdcApiProvider provider = new asdcApiProvider();
76          provider.setDataBroker( getDataBrokerDependency() );
77          provider.setNotificationService( getNotificationServiceDependency() );
78          provider.setRpcRegistry( getRpcRegistryDependency() );
79          provider.initialize();
80          return new AutoCloseable() {
81
82             @Override
83             public void close() throws Exception {
84                 //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION
85                 //SERVIE/RPC REGISTRY
86                 provider.close();
87             }
88         };
89     }
90
91
92     </pre>
93  */
94 public class AsdcApiProvider implements AutoCloseable, ASDCAPIService {
95
96     private static final String ACTIVE_VERSION = "active";
97
98     private final Logger log = LoggerFactory.getLogger( AsdcApiProvider.class );
99     private final String appName = "asdcApi";
100
101     private final ExecutorService executor;
102     protected DataBroker dataBroker;
103     protected NotificationProviderService notificationService;
104     protected RpcProviderRegistry rpcRegistry;
105
106     protected BindingAwareBroker.RpcRegistration<ASDCAPIService> rpcRegistration;
107
108     public AsdcApiProvider(DataBroker dataBroker2,
109             NotificationProviderService notificationProviderService,
110             RpcProviderRegistry rpcProviderRegistry) {
111         this.log.info( "Creating provider for " + appName );
112         executor = Executors.newFixedThreadPool(1);
113         dataBroker = dataBroker2;
114         notificationService = notificationProviderService;
115         rpcRegistry = rpcProviderRegistry;
116         initialize();
117     }
118
119     public void initialize(){
120         log.info( "Initializing provider for " + appName );
121
122
123         createContainers();
124
125         if (rpcRegistration == null) {
126             if (rpcRegistry != null) {
127                 rpcRegistration = rpcRegistry.addRpcImplementation(
128                         ASDCAPIService.class, this);
129                 log.info("Initialization complete for " + appName);
130             } else {
131                 log.warn("Error initializing " + appName
132                         + " : rpcRegistry unset");
133             }
134         }
135     }
136
137     private void createContainers() {
138
139         if (dataBroker != null) {
140         final WriteTransaction t = dataBroker.newReadWriteTransaction();
141
142         // Create the vf-model-license-versions and artifacts containers
143         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VfLicenseModelVersions.class),
144         new VfLicenseModelVersionsBuilder().build());
145
146         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Artifacts.class), new ArtifactsBuilder().build());
147
148
149         try {
150             CheckedFuture<Void, TransactionCommitFailedException> checkedFuture = t.submit();
151             checkedFuture.get();
152             log.info("Create Containers succeeded!: ");
153
154         } catch (InterruptedException | ExecutionException e) {
155             log.error("Create Containers Failed: " + e);
156             e.printStackTrace();
157         }
158         } else {
159             log.warn("createContainers : cannot find dataBroker to create containers");
160         }
161     }
162     protected void initializeChild() {
163         //Override if you have custom initialization intelligence
164     }
165
166     @Override
167     public void close() throws Exception {
168         log.info( "Closing provider for " + appName );
169         executor.shutdown();
170         rpcRegistration.close();
171         log.info( "Successfully closed provider for " + appName );
172     }
173
174     public void setDataBroker(DataBroker dataBroker) {
175         this.dataBroker = dataBroker;
176         if( log.isDebugEnabled() ){
177             log.debug( "DataBroker set to " + (dataBroker==null?"null":"non-null") + "." );
178         }
179     }
180
181     public void setNotificationService(
182             NotificationProviderService notificationService) {
183         this.notificationService = notificationService;
184         if( log.isDebugEnabled() ){
185             log.debug( "Notification Service set to " + (notificationService==null?"null":"non-null") + "." );
186         }
187     }
188
189     public void setRpcRegistry(RpcProviderRegistry rpcRegistry) {
190         this.rpcRegistry = rpcRegistry;
191
192         rpcRegistration = rpcRegistry.addRpcImplementation(ASDCAPIService.class, this);
193
194         if( log.isDebugEnabled() ){
195             log.debug( "RpcRegistry set to " + (rpcRegistry==null?"null":"non-null") + "." );
196         }
197     }
198
199
200     protected boolean artifactVersionExists(String aName, String aVersion) {
201         InstanceIdentifier artifactInstanceId =
202                 InstanceIdentifier.<Artifacts>builder(Artifacts.class)
203                 .child(Artifact.class, new ArtifactKey(aName, aVersion)).toInstance();
204         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
205         Optional<Artifact> data = null;
206         try {
207             data = (Optional<Artifact>) readTx.read(LogicalDatastoreType.CONFIGURATION, artifactInstanceId).get();
208         } catch (InterruptedException | ExecutionException e) {
209             log.error("Caught Exception reading MD-SAL for ["+aName+","+ aVersion+"] " ,e);
210             return false;
211
212         }
213
214         if (data.isPresent()) {
215             return true;
216         } else {
217             return false;
218         }
219     }
220
221     protected void addArtifactVersion(String aName, String aVersion) {
222
223
224         try {
225             ArtifactBuilder aBuilder = new ArtifactBuilder();
226
227             aBuilder.setArtifactName(aName);
228             aBuilder.setArtifactVersion(aVersion);
229
230             Artifact artifact = aBuilder.build();
231
232             InstanceIdentifier.InstanceIdentifierBuilder<Artifact> aIdBuilder = InstanceIdentifier
233                     .<Artifacts> builder(Artifacts.class)
234                     .child(Artifact.class, artifact.getKey());
235
236             InstanceIdentifier<Artifact> path = aIdBuilder
237                     .toInstance();
238
239             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
240
241             tx.merge(LogicalDatastoreType.CONFIGURATION, path,
242                     artifact);
243             tx.submit().checkedGet();
244         } catch (Exception e) {
245             log.error("Caught exception trying to add artifact entry", e);
246         }
247
248     }
249
250
251     private void applyVfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
252
253     String aName = input.getArtifactName();
254     String aVersion = input.getArtifactVersion();
255     VfLicenseModel vfLicenseModel = input.getVfLicenseModel();
256
257
258     // Add new version (version = artifact-version)
259     try {
260
261         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
262         vBuilder.setArtifactName(aName);
263         vBuilder.setArtifactVersion(aVersion);
264         vBuilder.setVfLicenseModel(vfLicenseModel);
265
266         VfLicenseModelVersion version = vBuilder.build();
267
268         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
269                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
270                 .child(VfLicenseModelVersion.class, version.getKey());
271
272         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder
273                 .toInstance();
274
275         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
276   tx.merge(LogicalDatastoreType.CONFIGURATION, path,
277                 version);
278         tx.submit().checkedGet();
279     } catch (Exception e) {
280         log.error(
281                 "Caught exception trying to save entry to MD-SAL",
282                 e);
283     }
284
285
286     // Add "active" version (version = "active")
287     try {
288
289         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
290         vBuilder.setArtifactName(aName);
291         vBuilder.setArtifactVersion(ACTIVE_VERSION);
292         vBuilder.setVfLicenseModel(vfLicenseModel);
293
294         VfLicenseModelVersion version = vBuilder.build();
295         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
296                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
297                 .child(VfLicenseModelVersion.class, version.getKey());
298
299         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder
300                 .toInstance();
301
302         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
303
304         tx.merge(LogicalDatastoreType.CONFIGURATION, path,
305                 version);
306         tx.submit().checkedGet();
307     } catch (Exception e) {
308         log.error(
309                 "Caught exception trying to save entry to MD-SAL",
310                 e);
311     }
312
313 }
314
315 @Override
316 public Future<RpcResult<VfLicenseModelUpdateOutput>> vfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
317     final String SVC_OPERATION = "vf-license-model-update";
318
319     Properties parms = new Properties();
320
321     log.info( SVC_OPERATION +" called." );
322
323     if(input == null ) {
324         log.debug("exiting " +SVC_OPERATION+ " because of invalid input");
325         return null;
326     }
327
328     VfLicenseModelUpdateInputBuilder inputBuilder = new VfLicenseModelUpdateInputBuilder(input);
329     input = inputBuilder.build();
330
331     String errorMessage = "Success";
332     String errorCode = "200";
333
334     // If this artifact already exists, reject this update
335     if (artifactVersionExists(input.getArtifactName(), input.getArtifactVersion())) {
336         errorCode = "409";
337         errorMessage = "Artifact version already exists";
338     } else {
339         // Translate input object into SLI-consumable properties
340         log.info("Adding INPUT data for "+SVC_OPERATION+" input: " + input);
341         AsdcApiUtil.toProperties(parms, input);
342
343
344         // Call directed graph
345
346         Properties respProps = null;
347
348
349         AsdcApiSliClient sliClient = new AsdcApiSliClient();
350         try
351         {
352             if (sliClient.hasGraph("ASDC-API", SVC_OPERATION , null, "sync"))
353             {
354
355                 try
356                 {
357                     respProps = sliClient.execute("ASDC-API", SVC_OPERATION, null, "sync", parms);
358                 }
359                 catch (Exception e)
360                 {
361                     log.error("Caught exception executing service logic for "+ SVC_OPERATION, e);
362                 }
363             } else {
364                 errorMessage = "No service logic active for ASDC-API: '" + SVC_OPERATION + "'";
365                 errorCode = "503";
366             }
367         }
368         catch (Exception e)
369         {
370             errorCode = "500";
371             errorMessage = e.getMessage();
372             log.error("Caught exception looking for service logic", e);
373         }
374
375
376         if (respProps != null)
377         {
378             errorCode = respProps.getProperty("error-code");
379             errorMessage = respProps.getProperty("error-message", "");
380         }
381     }
382
383
384     if ("200".equals(errorCode)) {
385         log.info("ASDC update succeeded");
386
387         // Update config tree
388         applyVfLicenseModelUpdate(input);
389         addArtifactVersion(input.getArtifactName(), input.getArtifactVersion());
390
391     } else {
392         log.info("ASDC update failed ("+errorCode+" : "+errorMessage);
393     }
394
395     // Send response
396     VfLicenseModelUpdateOutputBuilder respBuilder = new VfLicenseModelUpdateOutputBuilder();
397     respBuilder.setAsdcApiResponseCode(errorCode);
398     if (errorMessage != null && errorMessage.length() > 0) {
399         respBuilder.setAsdcApiResponseText(errorMessage);
400     }
401
402     RpcResult<VfLicenseModelUpdateOutput> rpcResult;
403
404
405     rpcResult = RpcResultBuilder.<VfLicenseModelUpdateOutput> status(true).withResult(respBuilder.build()).build();
406
407
408
409     return Futures.immediateFuture(rpcResult);
410 }
411
412
413 }