6010784e023d140f42eb7c77cb354a9f575cf5ba
[dmaap/dbcapi.git] / src / main / java / org / onap / dmaap / dbcapi / service / MR_ClientService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.onap.dmaap
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  *
7  * Modifications Copyright (C) 2019 IBM.
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.dmaap.dbcapi.service;
24
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.ws.rs.core.Response.Status;
30
31
32
33
34
35
36
37
38
39 import org.onap.dmaap.dbcapi.aaf.AafService;
40 import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
41 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
42 import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType;
43 import org.onap.dmaap.dbcapi.aaf.AafUserRole;
44 import org.onap.dmaap.dbcapi.client.MrProvConnection;
45 import org.onap.dmaap.dbcapi.database.DatabaseClass;
46 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
47 import org.onap.dmaap.dbcapi.model.ApiError;
48 import org.onap.dmaap.dbcapi.model.DcaeLocation;
49 import org.onap.dmaap.dbcapi.model.MR_Client;
50 import org.onap.dmaap.dbcapi.model.MR_Cluster;
51 import org.onap.dmaap.dbcapi.model.Topic;
52 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
53 import org.onap.dmaap.dbcapi.util.DmaapConfig;
54
55 public class MR_ClientService extends BaseLoggingClass{
56
57         private int deleteLevel;
58         private Map<String, MR_Client> mr_clients = DatabaseClass.getMr_clients();
59         private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters();
60         private Map<String, Topic> topics = DatabaseClass.getTopics();
61         private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations();
62         private DmaapService dmaap = new DmaapService();
63         private String centralCname;
64         
65         public MR_ClientService() {
66                 DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
67         
68                 centralCname = p.getProperty("MR.CentralCname", "MRcname.not.set");
69                 deleteLevel = Integer.valueOf(p.getProperty("MR.ClientDeleteLevel", "0" ));
70         }
71         
72         public Map<String, MR_Client> getMR_Clients() {                 
73                 return mr_clients;
74         }
75                 
76         public List<MR_Client> getAllMr_Clients() {
77                 return new ArrayList<MR_Client>(mr_clients.values());
78         }
79         
80         public ArrayList<MR_Client> getAllMrClients(String fqtn) {
81                 ArrayList<MR_Client> results = new ArrayList<>();
82                 for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet())
83                 {
84                         MR_Client client = entry.getValue();
85                     if ( fqtn.equals(client.getFqtn() ) ) {
86                         results.add( client );
87                     }
88                 }
89                 return results;
90         }       
91
92         public ArrayList<MR_Client> getClientsByLocation(String location) {
93                 ArrayList<MR_Client> results = new ArrayList<MR_Client>();
94                 for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet())
95                 {
96                         MR_Client client = entry.getValue();
97                     if ( location.equals(client.getDcaeLocationName() ) ) {
98                         results.add( client );
99                     }
100                 }
101                 return results;
102         }       
103         
104         public void refreshClients( String location ) {
105                 ApiError err = new ApiError();
106                 ArrayList<MR_Client> clients = getClientsByLocation( location );
107                 for( MR_Client client : clients ) {
108                         Topic topic = topics.get(client.getFqtn());
109                         if ( topic != null ) {
110                                 addMr_Client( client, topic, err);
111                         }
112                         
113                         
114                 }
115         }
116         
117         public MR_Client getMr_Client( String key, ApiError apiError ) {                        
118                 MR_Client c =  mr_clients.get( key );
119                 if ( c == null ) {
120                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
121                         apiError.setFields( "mrClientId");
122                         apiError.setMessage("mrClientId " + key + " not found" );
123                 } else {
124                         apiError.setCode(200);
125                 }
126                 return c;
127         }
128
129         public MR_Client addMr_Client( MR_Client client, Topic topic, ApiError err ) {
130                 if ( client.getDcaeLocationName().isEmpty()) {
131                         logger.info( "Client  dcaeLocation that doesn't exist or not specified" );
132                         return null;
133                 }
134                 // original style: clients specified Role.  This has precedence for backwards
135                 //                 compatibility.
136                 // ONAP style: clients specify Identity to be assigned to generated Role
137                 String role = client.getClientRole();
138                 if ( role != null ) {
139                         grantClientRolePerms(  client,  err);
140                 } else if ( client.hasClientIdentity() ){
141                         if ( client.isSubscriber() ) {
142                                 role = topic.getSubscriberRole();
143                                 assignIdentityToRole( client, role, err );
144                         } 
145                         if (client.isPublisher() ) {
146                                 role = topic.getPublisherRole();
147                                 assignIdentityToRole( client, role, err );
148                         }       
149                 } 
150                 if ( ! client.isStatusValid()) {
151                         return null;
152                 }
153                 String centralFqdn = null;
154                 DcaeLocation candidate = locations.get(client.getDcaeLocationName());
155
156                 MR_Cluster cluster = clusters.get( client.getDcaeLocationName());
157                 if (  cluster != null && candidate != null ) {
158                         if ( candidate.isCentral() && ! topic.getReplicationCase().involvesFQDN() ) {
159                                 centralFqdn = centralCname;
160                         }
161                         client.setTopicURL(cluster.genTopicURL(centralFqdn, client.getFqtn()));
162                         if ( centralFqdn == null ) {
163                                 client.setStatus( addTopicToCluster( cluster, topic, err));
164                                 if( ! err.is2xx() && err.getCode() != 409 ) {
165                                         topic.setFqtn(err.getMessage());
166                                         return null;
167                                 }
168                         
169                         } else {
170                                 MR_ClusterService clusters = new MR_ClusterService();   
171                                 //  MM should only exist for edge-to-central
172                                 //  we use a cname for the central target (default resiliency with no replicationGroup set)
173                                 // but still need to provision topics on all central MRs
174                                 for( MR_Cluster central: clusters.getCentralClusters() ) {
175                                         client.setStatus( addTopicToCluster( central, topic, err));
176                                         if( ! err.is2xx() && err.getCode() != 409 ) {
177                                                 topic.setFqtn(err.getMessage());
178                                                 return null;
179                                         }
180                                 }
181                         }
182                         
183                 } else {
184                         logger.warn( "Client references a dcaeLocation that doesn't exist:" + client.getDcaeLocationName());
185                         client.setStatus( DmaapObject_Status.STAGED);
186                         //return null;
187                 }
188
189                 mr_clients.put( client.getMrClientId(), client );
190
191                 err.setCode(200);
192                 
193                 return client;
194         }
195         
196         private DmaapObject_Status addTopicToCluster( MR_Cluster cluster, Topic topic, ApiError err  ){
197                 
198                 MrProvConnection prov = new MrProvConnection();
199                 logger.info( "POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName());
200                 if ( prov.makeTopicConnection(cluster)) {
201                         String resp = prov.doPostTopic(topic, err);
202                         logger.info( "response code: " + err.getCode() );
203                         if ( err.is2xx() || err.getCode() == 409 ) {
204                                 return DmaapObject_Status.VALID;
205                         } 
206                 }
207                 return DmaapObject_Status.INVALID;
208         }
209         
210         private void grantClientRolePerms( MR_Client client, ApiError err) {
211                 AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
212                 
213                 String instance = ":topic." + client.getFqtn();
214                 client.setStatus( DmaapObject_Status.VALID);
215                 String role = client.getClientRole();
216                 for( String want : client.getAction() ) {
217                         int rc;
218                         DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want );
219                         if ( role != null ) {
220                                 DmaapGrant g = new DmaapGrant( perm, role );
221                                 rc = aaf.addGrant( g );
222                                 if ( rc != 201 && rc != 409 ) {
223                                         client.setStatus( DmaapObject_Status.INVALID);
224                                         err.setCode(rc);
225                                         err.setMessage( "Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + role );
226                                         logger.warn( err.getMessage());
227                                         return;
228                                 } 
229                         } else {
230                                 logger.warn( "No Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " because role is null " );
231                         }
232                 }
233         }
234         
235         private void assignIdentityToRole( MR_Client client, String role, ApiError err ) {
236                 AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
237
238                 AafUserRole ur = new AafUserRole( client.getClientIdentity(), role );
239                 int rc = aaf.addUserRole( ur );
240                 if ( rc != 201 && rc != 409 ) {
241                         client.setStatus( DmaapObject_Status.INVALID);
242                         err.setCode(rc);
243                         err.setMessage( "Failed to add user " + client.getClientIdentity()+  "  to " + role );
244                         logger.warn( err.getMessage());
245                         return;
246                 }
247                 client.setStatus( DmaapObject_Status.VALID);
248
249         }
250         private void revokeClientPerms( MR_Client client, ApiError err) {
251                 AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
252                 
253                 String instance = ":topic." + client.getFqtn();
254                 client.setStatus( DmaapObject_Status.VALID);
255                 for( String want : client.getAction() ) {
256                         int rc;
257                         DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want );
258                         DmaapGrant g = new DmaapGrant( perm, client.getClientRole() );
259                         rc = aaf.delGrant( g );
260                         if ( rc != 200 && rc != 404 ) {
261                                 client.setStatus( DmaapObject_Status.INVALID);
262                                 err.setCode(rc);
263                                 err.setMessage( "Revoke of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() );
264                                 logger.warn( err.getMessage());
265                                 return;
266                         } 
267                 }
268         }
269         
270         public MR_Client updateMr_Client( MR_Client client, ApiError apiError ) {
271                 MR_Client c =  mr_clients.get( client.getMrClientId());
272                 if ( c == null ) {
273                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
274                         apiError.setFields( "mrClientId");
275                         apiError.setMessage("mrClientId " + client.getMrClientId() + " not found" );
276                 } else {
277                         apiError.setCode(200);
278                 }
279                 mr_clients.put( client.getMrClientId(), client );
280                 return client;
281         }
282                 
283         public void removeMr_Client( String key, boolean updateTopicView, ApiError apiError ) {
284                 MR_Client client =  mr_clients.get( key );
285                 if ( client == null ) {
286                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
287                         apiError.setFields( "mrClientId");
288                         apiError.setMessage("mrClientId " + key + " not found" );
289                         return;
290                 } else {
291                         apiError.setCode(200);
292                 }
293                 
294                 if ( updateTopicView == true ) {
295
296                         TopicService topics = new TopicService();
297                         
298                         Topic t = topics.getTopic(client.getFqtn(), apiError );
299                         if ( t != null ) {      
300                                 ArrayList<MR_Client> tc = t.getClients();
301                                 for( MR_Client c: tc) {
302                                         if ( c.getMrClientId().equals(client.getMrClientId())) {
303                                                 tc.remove(c);
304                                                 break;
305                                         }
306                                 }
307                                 t.setClients(tc);
308                                 topics.updateTopic( t, apiError );
309                         }
310
311                 }
312
313                 
314                 // remove from AAF
315                 if ( deleteLevel >= 2 ) {
316                         revokeClientPerms( client, apiError );
317                         if ( ! apiError.is2xx()) {
318                                 return;
319                         }
320                 }
321                 // remove from DB 
322                 if ( deleteLevel >= 1 ) {
323                         mr_clients.remove(key);
324                 }
325
326                 return;
327         }
328         
329 }