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