Alternative MR replication method
[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.client.MrProvConnection;
42 import org.onap.dmaap.dbcapi.database.DatabaseClass;
43 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
44 import org.onap.dmaap.dbcapi.model.ApiError;
45 import org.onap.dmaap.dbcapi.model.DcaeLocation;
46 import org.onap.dmaap.dbcapi.model.MR_Client;
47 import org.onap.dmaap.dbcapi.model.MR_Cluster;
48 import org.onap.dmaap.dbcapi.model.Topic;
49 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
50 import org.onap.dmaap.dbcapi.util.DmaapConfig;
51
52 public class MR_ClientService extends BaseLoggingClass{
53
54         private int deleteLevel;
55         private Map<String, MR_Client> mr_clients = DatabaseClass.getMr_clients();
56         private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters();
57         private Map<String, Topic> topics = DatabaseClass.getTopics();
58         private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations();
59         private DmaapService dmaap = new DmaapService();
60         private String centralCname;
61         
62         public MR_ClientService() {
63                 DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
64         
65                 centralCname = p.getProperty("MR.CentralCname", "MRcname.not.set");
66                 deleteLevel = Integer.valueOf(p.getProperty("MR.ClientDeleteLevel", "0" ));
67         }
68         
69         public Map<String, MR_Client> getMR_Clients() {                 
70                 return mr_clients;
71         }
72                 
73         public List<MR_Client> getAllMr_Clients() {
74                 return new ArrayList<MR_Client>(mr_clients.values());
75         }
76         
77         public ArrayList<MR_Client> getAllMrClients(String fqtn) {
78                 ArrayList<MR_Client> results = new ArrayList<MR_Client>();
79                 for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet())
80                 {
81                         MR_Client client = entry.getValue();
82                     if ( fqtn.equals(client.getFqtn() ) ) {
83                         results.add( client );
84                     }
85                 }
86                 return results;
87         }       
88
89         public ArrayList<MR_Client> getClientsByLocation(String location) {
90                 ArrayList<MR_Client> results = new ArrayList<MR_Client>();
91                 for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet())
92                 {
93                         MR_Client client = entry.getValue();
94                     if ( location.equals(client.getDcaeLocationName() ) ) {
95                         results.add( client );
96                     }
97                 }
98                 return results;
99         }       
100         
101         public void refreshClients( String location ) {
102                 ApiError err = new ApiError();
103                 ArrayList<MR_Client> clients = getClientsByLocation( location );
104                 for( MR_Client client : clients ) {
105                         Topic topic = topics.get(client.getFqtn());
106                         if ( topic != null ) {
107                                 addMr_Client( client, topic, err);
108                         }
109                         
110                         
111                 }
112         }
113         
114         public MR_Client getMr_Client( String key, ApiError apiError ) {                        
115                 MR_Client c =  mr_clients.get( key );
116                 if ( c == null ) {
117                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
118                         apiError.setFields( "mrClientId");
119                         apiError.setMessage("mrClientId " + key + " not found" );
120                 } else {
121                         apiError.setCode(200);
122                 }
123                 return c;
124         }
125
126         public MR_Client addMr_Client( MR_Client client, Topic topic, ApiError err ) {
127                 if ( client.getDcaeLocationName().isEmpty()) {
128                         logger.info( "Client  dcaeLocation that doesn't exist or not specified" );
129                         return null;
130                 }
131                 grantClientPerms(  client,  err);
132                 if ( ! client.isStatusValid()) {
133                         return null;
134                 }
135                 String centralFqdn = null;
136                 DcaeLocation candidate = locations.get(client.getDcaeLocationName());
137
138                 MR_Cluster cluster = clusters.get( client.getDcaeLocationName());
139                 if (  cluster != null && candidate != null ) {
140                         if ( candidate.isCentral() && ! topic.getReplicationCase().involvesFQDN() ) {
141                                 centralFqdn = centralCname;
142                         }
143                         client.setTopicURL(cluster.genTopicURL(centralFqdn, client.getFqtn()));
144                         if ( centralFqdn == null ) {
145                                 client.setStatus( addTopicToCluster( cluster, topic, err));
146                                 if( ! err.is2xx() && err.getCode() != 409 ) {
147                                         topic.setFqtn(err.getMessage());
148                                         return null;
149                                 }
150                         
151                         } else {
152                                 MR_ClusterService clusters = new MR_ClusterService();   
153                                 //  MM should only exist for edge-to-central
154                                 //  we use a cname for the central target (default resiliency with no replicationGroup set)
155                                 // but still need to provision topics on all central MRs
156                                 for( MR_Cluster central: clusters.getCentralClusters() ) {
157                                         client.setStatus( addTopicToCluster( central, topic, err));
158                                         if( ! err.is2xx() && err.getCode() != 409 ) {
159                                                 topic.setFqtn(err.getMessage());
160                                                 return null;
161                                         }
162                                 }
163                         }
164                         
165                 } else {
166                         logger.warn( "Client references a dcaeLocation that doesn't exist:" + client.getDcaeLocationName());
167                         client.setStatus( DmaapObject_Status.STAGED);
168                         //return null;
169                 }
170
171                 mr_clients.put( client.getMrClientId(), client );
172
173                 err.setCode(200);
174                 
175                 return client;
176         }
177         
178         private DmaapObject_Status addTopicToCluster( MR_Cluster cluster, Topic topic, ApiError err  ){
179                 
180                 MrProvConnection prov = new MrProvConnection();
181                 logger.info( "POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName());
182                 if ( prov.makeTopicConnection(cluster)) {
183                         String resp = prov.doPostTopic(topic, err);
184                         logger.info( "response code: " + err.getCode() );
185                         if ( err.is2xx() || err.getCode() == 409 ) {
186                                 return DmaapObject_Status.VALID;
187                         } 
188                 }
189                 return DmaapObject_Status.INVALID;
190         }
191         
192         private void grantClientPerms( MR_Client client, ApiError err) {
193                 AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
194                 
195                 String instance = ":topic." + client.getFqtn();
196                 client.setStatus( DmaapObject_Status.VALID);
197                 for( String want : client.getAction() ) {
198                         int rc;
199                         DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want );
200                         DmaapGrant g = new DmaapGrant( perm, client.getClientRole() );
201                         rc = aaf.addGrant( g );
202                         if ( rc != 201 && rc != 409 ) {
203                                 client.setStatus( DmaapObject_Status.INVALID);
204                                 err.setCode(rc);
205                                 err.setMessage( "Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() );
206                                 logger.warn( err.getMessage());
207                                 return;
208                         } 
209                 }
210         }
211         
212         private void revokeClientPerms( MR_Client client, ApiError err) {
213                 AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
214                 
215                 String instance = ":topic." + client.getFqtn();
216                 client.setStatus( DmaapObject_Status.VALID);
217                 for( String want : client.getAction() ) {
218                         int rc;
219                         DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want );
220                         DmaapGrant g = new DmaapGrant( perm, client.getClientRole() );
221                         rc = aaf.delGrant( g );
222                         if ( rc != 200 && rc != 404 ) {
223                                 client.setStatus( DmaapObject_Status.INVALID);
224                                 err.setCode(rc);
225                                 err.setMessage( "Revoke of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() );
226                                 logger.warn( err.getMessage());
227                                 return;
228                         } 
229                 }
230         }
231         
232         public MR_Client updateMr_Client( MR_Client client, ApiError apiError ) {
233                 MR_Client c =  mr_clients.get( client.getMrClientId());
234                 if ( c == null ) {
235                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
236                         apiError.setFields( "mrClientId");
237                         apiError.setMessage("mrClientId " + client.getMrClientId() + " not found" );
238                 } else {
239                         apiError.setCode(200);
240                 }
241                 mr_clients.put( client.getMrClientId(), client );
242                 return client;
243         }
244                 
245         public void removeMr_Client( String key, boolean updateTopicView, ApiError apiError ) {
246                 MR_Client client =  mr_clients.get( key );
247                 if ( client == null ) {
248                         apiError.setCode(Status.NOT_FOUND.getStatusCode());
249                         apiError.setFields( "mrClientId");
250                         apiError.setMessage("mrClientId " + key + " not found" );
251                         return;
252                 } else {
253                         apiError.setCode(200);
254                 }
255                 
256                 if ( updateTopicView == true ) {
257
258                         TopicService topics = new TopicService();
259                         
260                         Topic t = topics.getTopic(client.getFqtn(), apiError );
261                         if ( t != null ) {      
262                                 ArrayList<MR_Client> tc = t.getClients();
263                                 for( MR_Client c: tc) {
264                                         if ( c.getMrClientId().equals(client.getMrClientId())) {
265                                                 tc.remove(c);
266                                                 break;
267                                         }
268                                 }
269                                 t.setClients(tc);
270                                 topics.updateTopic( t, apiError );
271                         }
272
273                 }
274
275                 
276                 // remove from AAF
277                 if ( deleteLevel >= 2 ) {
278                         revokeClientPerms( client, apiError );
279                         if ( ! apiError.is2xx()) {
280                                 return;
281                         }
282                 }
283                 // remove from DB 
284                 if ( deleteLevel >= 1 ) {
285                         mr_clients.remove(key);
286                 }
287
288                 return;
289         }
290         
291 }