Containerization feature of SO
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / tenant / MsoTenantAdapterImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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.so.adapters.tenant;
22
23
24 import java.util.Map;
25
26 import javax.annotation.Resource;
27 import javax.jws.WebService;
28 import javax.xml.ws.Holder;
29 import javax.xml.ws.WebServiceContext;
30
31 import org.onap.so.adapters.tenant.exceptions.TenantAlreadyExists;
32 import org.onap.so.adapters.tenant.exceptions.TenantException;
33 import org.onap.so.adapters.tenantrest.TenantRollback;
34 import org.onap.so.entity.MsoRequest;
35 import org.onap.so.logger.MessageEnum;
36 import org.onap.so.logger.MsoLogger;
37 import org.onap.so.openstack.beans.MsoTenant;
38 import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
39 import org.onap.so.openstack.exceptions.MsoException;
40 import org.onap.so.openstack.utils.MsoTenantUtils;
41 import org.onap.so.openstack.utils.MsoTenantUtilsFactory;
42 import org.springframework.beans.factory.annotation.Autowired;
43 import org.springframework.stereotype.Component;
44
45 @WebService(serviceName = "TenantAdapter", endpointInterface = "org.onap.so.adapters.tenant.MsoTenantAdapter", targetNamespace = "http://org.onap.so/tenant")
46 @Component
47 public class MsoTenantAdapterImpl implements MsoTenantAdapter {
48         public static final String CREATE_TENANT = "CreateTenant";
49     public static final String OPENSTACK = "OpenStack";
50     public static final String QUERY_TENANT = "QueryTenant";
51     public static final String DELETE_TENANT = "DeleteTenant";
52     public static final String ROLLBACK_TENANT = "RollbackTenant";
53         
54     @Resource
55     private WebServiceContext wsContext;
56
57     @Autowired
58         private MsoTenantUtilsFactory tFactory;
59     private static MsoLogger logger = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoTenantAdapterImpl.class);
60     /**
61      * Health Check web method. Does nothing but return to show the adapter is deployed.
62      */
63     @Override
64     public void healthCheck () {
65         logger.debug ("Health check call in Tenant Adapter");
66     }
67
68     /**
69      * This is the "Create Tenant" web service implementation. It will create
70      * a new Tenant in the specified cloud. If the tenant already exists, this
71      * can be considered a success or failure, depending on the value of the
72      * 'failIfExists' parameter.
73      *
74      * The method returns the tenantId (the Openstack ID), and a TenantRollback
75      * object. This last object can be passed as-is to the rollbackTenant method
76      * to undo what (if anything) was created. This is useful if a Tenant is
77      * successfully created but the orchestrator fails on a subsequent operation.
78      */
79     @Override
80     public void createTenant (String cloudSiteId,
81                               String tenantName,
82                               Map <String, String> metadata,
83                               Boolean failIfExists,
84                               Boolean backout,
85                               MsoRequest msoRequest,
86                               Holder <String> tenantId,
87                               Holder <TenantRollback> rollback) throws TenantException, TenantAlreadyExists {
88         MsoLogger.setLogContext (msoRequest);
89         MsoLogger.setServiceName (CREATE_TENANT);
90
91         logger.debug ("Call to MSO createTenant adapter. Creating Tenant: " + tenantName
92                                       + "in "
93                                       + cloudSiteId);
94
95         // Will capture total time for metrics
96         long startTime = System.currentTimeMillis ();
97
98         // Start building up rollback object
99         TenantRollback tenantRollback = new TenantRollback ();
100         tenantRollback.setCloudId (cloudSiteId);
101         tenantRollback.setMsoRequest (msoRequest);
102         
103         MsoTenantUtils tUtils;
104                 try {
105                         tUtils = tFactory.getTenantUtils (cloudSiteId);
106                 } catch (MsoCloudSiteNotFound me) {
107             logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "no implementation found for " + cloudSiteId, me);
108             throw new TenantException (me);
109                 }
110
111         MsoTenant newTenant = null;
112         String newTenantId;
113         long queryTenantStartTime = System.currentTimeMillis ();
114         try {
115             newTenant = tUtils.queryTenantByName (tenantName, cloudSiteId);
116             logger.recordMetricEvent (queryTenantStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, QUERY_TENANT, null);
117         } catch (MsoException me) {
118             logger.recordMetricEvent (queryTenantStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with Open Stack", OPENSTACK, QUERY_TENANT, null);
119             String error = "Create Tenant " + tenantName + ": " + me;
120             logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "Exception while communicate with Open Stack", me);
121             logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
122             throw new TenantException (me);
123         }
124         if (newTenant == null) {
125             if (backout == null)
126                 backout = true;
127             long createTenantStartTime = System.currentTimeMillis ();
128             try {
129                 newTenantId = tUtils.createTenant (tenantName, cloudSiteId, metadata, backout.booleanValue ());
130                 logger.recordMetricEvent (createTenantStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, CREATE_TENANT, null);
131             } catch (MsoException me) {
132                 logger.recordMetricEvent (createTenantStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with Open Stack", OPENSTACK, CREATE_TENANT, null);
133                 String error = "Create Tenant " + tenantName + ": " + me;
134                 logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "Exception while communicate with Open Stack", me);
135                 logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
136                 throw new TenantException (me);
137             }
138             tenantRollback.setTenantId (newTenantId);
139             tenantRollback.setTenantCreated (true);
140             logger.debug ("Tenant " + tenantName + " successfully created with ID " + newTenantId);
141         } else {
142             if (failIfExists != null && failIfExists) {
143                 String error = CREATE_TENANT + ": Tenant " + tenantName + " already exists in " + cloudSiteId;
144                 logger.error (MessageEnum.RA_TENANT_ALREADY_EXIST, tenantName, cloudSiteId, OPENSTACK, "", MsoLogger.ErrorCode.DataError, CREATE_TENANT + ", Tenant already exists");
145                 logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
146                 throw new TenantAlreadyExists (tenantName, cloudSiteId, newTenant.getTenantId ());
147             }
148
149             newTenantId = newTenant.getTenantId ();
150             tenantRollback.setTenantCreated (false);
151             logger.debug ("Tenant " + tenantName + " already exists with ID " + newTenantId);
152         }
153
154
155         tenantId.value = newTenantId;
156         rollback.value = tenantRollback;
157         logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create tenant");
158         return;
159     }
160
161     @Override
162     public void queryTenant (String cloudSiteId,
163                              String tenantNameOrId,
164                              MsoRequest msoRequest,
165                              Holder <String> tenantId,
166                              Holder <String> tenantName,
167                              Holder <Map <String, String>> metadata) throws TenantException {
168         MsoLogger.setLogContext (msoRequest);
169         MsoLogger.setServiceName (QUERY_TENANT);
170         logger.debug ("Querying Tenant " + tenantNameOrId + " in " + cloudSiteId);
171
172         // Will capture execution time for metrics
173         long startTime = System.currentTimeMillis ();
174
175         MsoTenantUtils tUtils;
176                 try {
177                         tUtils = tFactory.getTenantUtils (cloudSiteId);
178                 } catch (MsoCloudSiteNotFound me) {
179             logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "no implementation found for " + cloudSiteId, me);
180             throw new TenantException (me);
181                 }
182         
183         MsoTenant qTenant = null;
184         long subStartTime = System.currentTimeMillis ();
185         try {
186             qTenant = tUtils.queryTenant (tenantNameOrId, cloudSiteId);
187             logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, QUERY_TENANT, null);
188             if (qTenant == null) {
189                 // Not found by ID, Try by name.
190                 qTenant = tUtils.queryTenantByName (tenantNameOrId, cloudSiteId);
191             }
192
193             if (qTenant == null) {
194                 logger.debug ("QueryTenant: Tenant " + tenantNameOrId + " not found");
195                 tenantId.value = null;
196                 tenantName.value = null;
197                 metadata.value = null;
198             } else {
199                 logger.debug ("QueryTenant: Tenant " + tenantNameOrId + " found with ID " + qTenant.getTenantId ());
200                 tenantId.value = qTenant.getTenantId ();
201                 tenantName.value = qTenant.getTenantName ();
202                 metadata.value = qTenant.getMetadata ();
203             }
204         } catch (MsoException me) {
205             String error = "Query Tenant " + tenantNameOrId + ": " + me;
206             logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, QUERY_TENANT, null);
207             logger.error (MessageEnum.RA_GENERAL_EXCEPTION, me.getMessage(), OPENSTACK, "", MsoLogger.ErrorCode.DataError, "Exception in queryTenant", me);
208             logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
209             throw new TenantException (me);
210         }
211         logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query tenant");
212         return;
213     }
214
215     @Override
216     public void deleteTenant (String cloudSiteId,
217                               String tenantId,
218                               MsoRequest msoRequest,
219                               Holder <Boolean> tenantDeleted) throws TenantException {
220         MsoLogger.setLogContext (msoRequest);
221         MsoLogger.setServiceName (DELETE_TENANT);
222
223         logger.debug ("Deleting Tenant " + tenantId + " in " + cloudSiteId);
224
225         // Will capture execution time for metrics
226         long startTime = System.currentTimeMillis ();
227
228         // Delete the Tenant.
229         long subStartTime = System.currentTimeMillis ();
230         try {
231                 
232                 MsoTenantUtils tUtils = tFactory.getTenantUtils (cloudSiteId);
233             boolean deleted = tUtils.deleteTenant (tenantId, cloudSiteId);
234             tenantDeleted.value = deleted;
235             logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully communicate with Open Stack", OPENSTACK, DELETE_TENANT, null);
236         } catch (MsoException me) {
237             String error = "Delete Tenant " + tenantId + ": " + me;
238             logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, DELETE_TENANT, null);
239             logger.error (MessageEnum.RA_DELETE_TEMAMT_ERR, me.getMessage(), OPENSTACK, "", MsoLogger.ErrorCode.DataError, "Exception - DeleteTenant", me);
240             logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
241             throw new TenantException (me);
242         }
243
244         // On success, nothing is returned.
245         logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete tenant");
246         return;
247     }
248
249     /**
250      * This web service endpoint will rollback a previous Create VNF operation.
251      * A rollback object is returned to the client in a successful creation
252      * response. The client can pass that object as-is back to the rollbackVnf
253      * operation to undo the creation.
254      *
255      * The rollback includes removing the VNF and deleting the tenant if the
256      * tenant did not exist prior to the VNF creation.
257      */
258     @Override
259     public void rollbackTenant (TenantRollback rollback) throws TenantException {
260         long startTime = System.currentTimeMillis ();
261         MsoLogger.setServiceName (ROLLBACK_TENANT);
262         // rollback may be null (e.g. if stack already existed when Create was called)
263         if (rollback == null) {
264             logger.warn (MessageEnum.RA_ROLLBACK_NULL, OPENSTACK, "rollbackTenant", MsoLogger.ErrorCode.DataError, "rollbackTenant, rollback is null");
265             return;
266         }
267
268         // Get the elements of the VnfRollback object for easier access
269         String cloudSiteId = rollback.getCloudId ();
270         String tenantId = rollback.getTenantId ();
271
272         MsoLogger.setLogContext (rollback.getMsoRequest ());
273         logger.debug ("Rolling Back Tenant " + rollback.getTenantId () + " in " + cloudSiteId);
274
275         long subStartTime = System.currentTimeMillis ();
276         if (rollback.getTenantCreated ()) {
277             try {
278                  
279                 MsoTenantUtils tUtils = tFactory.getTenantUtils (cloudSiteId);
280                 tUtils.deleteTenant (tenantId, cloudSiteId);
281                 logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully communicate with Open Stack", OPENSTACK, ROLLBACK_TENANT, null);
282             } catch (MsoException me) {
283                 me.addContext (ROLLBACK_TENANT);
284                 // Failed to delete the tenant.
285                 String error = "Rollback Tenant " + tenantId + ": " + me;
286                 logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, ROLLBACK_TENANT, null);
287                 logger.error (MessageEnum.RA_ROLLBACK_TENANT_ERR, me.getMessage(), OPENSTACK, "rollbackTenant", MsoLogger.ErrorCode.DataError, "Exception - rollbackTenant", me);
288                 logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
289                 throw new TenantException (me);
290             }
291         }
292         logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully roll back tenant");
293         return;
294     }
295 }