Updating licenses in all files
[appc.git] / appc-adapters / appc-iaas-adapter / appc-iaas-adapter-bundle / src / main / java / org / openecomp / appc / adapter / iaas / provider / operation / impl / RebuildServer.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Amdocs
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  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22
23 package org.openecomp.appc.adapter.iaas.provider.operation.impl;
24
25 import org.openecomp.appc.Constants;
26 import org.openecomp.appc.adapter.iaas.ProviderAdapter;
27 import org.openecomp.appc.adapter.iaas.impl.IdentityURL;
28 import org.openecomp.appc.adapter.iaas.impl.RequestContext;
29 import org.openecomp.appc.adapter.iaas.impl.RequestFailedException;
30 import org.openecomp.appc.adapter.iaas.impl.VMURL;
31 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation;
32 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome;
33 import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation;
34 import org.openecomp.appc.configuration.Configuration;
35 import org.openecomp.appc.configuration.ConfigurationFactory;
36 import org.openecomp.appc.exceptions.APPCException;
37 import org.openecomp.appc.i18n.Msg;
38 import com.att.cdp.exceptions.ContextConnectionException;
39 import com.att.cdp.exceptions.ResourceNotFoundException;
40 import com.att.cdp.exceptions.ZoneException;
41 import com.att.cdp.zones.ComputeService;
42 import com.att.cdp.zones.Context;
43 import com.att.cdp.zones.ImageService;
44 import com.att.cdp.zones.Provider;
45 import com.att.cdp.zones.model.Image;
46 import com.att.cdp.zones.model.ModelObject;
47 import com.att.cdp.zones.model.Server;
48 import com.att.cdp.zones.model.ServerBootSource;
49 import com.att.eelf.configuration.EELFLogger;
50 import com.att.eelf.configuration.EELFManager;
51 import com.att.eelf.i18n.EELFResourceManager;
52 import org.openecomp.sdnc.sli.SvcLogicContext;
53 import org.glassfish.grizzly.http.util.HttpStatus;
54
55 import java.util.List;
56 import java.util.Map;
57
58 import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE;
59 import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE;
60 import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME;
61
62 import org.slf4j.MDC;
63 import java.text.DateFormat;
64 import java.text.SimpleDateFormat;
65 import java.util.Date;
66 import java.util.TimeZone;
67
68 /**
69  * @since September 26, 2016
70  */
71 public class RebuildServer extends ProviderServerOperation {
72
73     private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class);
74     private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
75     private static final Configuration configuration = ConfigurationFactory.getConfiguration();
76
77     /**
78      * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be
79      * in the correct state to do the rebuild.
80      *
81      * @param rc
82      *            The request context that manages the state and recovery of the request for the life of its processing.
83      * @param server
84      *            the server to be rebuilt
85      * @param image
86      *            The image to be used (or snapshot)
87      * @throws RequestFailedException
88      *             if the server does not change state in the allotted time
89      */
90     @SuppressWarnings("nls")
91     private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException {
92         logger.debug(Msg.REBUILD_SERVER, server.getId());
93         
94         String msg;
95         Context context = server.getContext();
96         Provider provider = context.getProvider();
97         ComputeService service = context.getComputeService();  
98         
99         /*
100          * Set Time for Metrics Logger
101          */
102         long startTime = System.currentTimeMillis();
103         TimeZone tz = TimeZone.getTimeZone("UTC");
104         DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
105         df.setTimeZone(tz);
106         String startTimeStr = df.format(new Date());
107         long endTime = System.currentTimeMillis();
108         long duration = endTime - startTime;
109         String endTimeStr = String.valueOf(endTime);
110         String durationStr = String.valueOf(duration);
111         String endTimeStrUTC = df.format(new Date());
112         MDC.put("EndTimestamp", endTimeStrUTC);
113         MDC.put("ElapsedTime", durationStr);
114         MDC.put("TargetEntity", "cdp");
115         MDC.put("TargetServiceName", "rebuild server");
116         MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer"); 
117
118         try {
119             while (rc.attempt()) {
120                 try {
121                     server.rebuild(image);
122                     break;
123                 } catch (ContextConnectionException e) {
124                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
125                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
126                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
127                             Integer.toString(rc.getRetryLimit()));
128                     logger.error(msg, e);
129                     metricsLogger.error(msg,e);
130                     rc.delay();
131                 }
132             }
133
134             /*
135              * We need to provide some time for OpenStack to start processing the request.
136              */
137             try {
138                 Thread.sleep(10L * 1000L);
139             } catch (InterruptedException e) {
140                 logger.trace("Sleep threw interrupted exception, should never occur");
141                 metricsLogger.trace("Sleep threw interrupted exception, should never occur");
142             }
143         } catch (ZoneException e) {
144             msg =
145                     EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), e.getMessage());
146             logger.error(msg);
147             metricsLogger.error(msg);
148             throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
149         }
150
151         rc.reset();
152         /*
153          * Once we have started the process, now we wait for the final state of stopped. This should be the final state
154          * (since we started the rebuild with the server stopped).
155          */
156         waitForStateChange(rc, server, Server.Status.READY);
157
158         if (rc.isFailed()) {
159             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
160             logger.error(msg);
161             metricsLogger.error(msg);
162             throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
163         }
164         rc.reset();
165     }
166
167     /**
168      * This method is called to rebuild the provided server.
169      * <p>
170      * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding
171      * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose.
172      * </p>
173      *
174      * @param rc
175      *            The request context that manages the state and recovery of the request for the life of its processing.
176      * @param server
177      * @throws ZoneException
178      * @throws RequestFailedException
179      */
180     @SuppressWarnings("nls")
181         private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx)
182                         throws ZoneException, RequestFailedException {
183
184                 ServerBootSource builtFrom = server.getBootSource();
185                 String msg;
186
187                 /*
188                  * Set Time for Metrics Logger
189                  */
190                 long startTime = System.currentTimeMillis();
191                 TimeZone tz = TimeZone.getTimeZone("UTC");
192                 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
193                 df.setTimeZone(tz);
194                 String startTimeStr = df.format(new Date());
195                 long endTime = System.currentTimeMillis();
196                 long duration = endTime - startTime;
197                 String endTimeStr = String.valueOf(endTime);
198                 String durationStr = String.valueOf(duration);
199                 String endTimeStrUTC = df.format(new Date());
200                 MDC.put("EndTimestamp", endTimeStrUTC);
201                 MDC.put("ElapsedTime", durationStr);
202                 MDC.put("TargetEntity", "cdp");
203                 MDC.put("TargetServiceName", "rebuild server");
204                 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
205
206                 // Throw exception for non image/snap boot source
207                 if (ServerBootSource.VOLUME.equals(builtFrom)) {
208                         msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]",
209                                         server.getId());
210                         generateEvent(rc, false, msg);
211                         logger.error(msg);
212                         metricsLogger.error(msg);
213                         throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server);
214                 }
215
216                 /*
217                  * Pending is a bit of a special case. If we find the server is in a
218                  * pending state, then the provider is in the process of changing state
219                  * of the server. So, lets try to wait a little bit and see if the state
220                  * settles down to one we can deal with. If not, then we have to fail
221                  * the request.
222                  */
223                 Context context = server.getContext();
224                 Provider provider = context.getProvider();
225                 ComputeService service = context.getComputeService();
226                 if (server.getStatus().equals(Server.Status.PENDING)) {
227             rc.reset();
228             waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR,
229                                         Server.Status.SUSPENDED, Server.Status.PAUSED);
230                 }
231
232                 // Is the skip Hypervisor check attribute populated?
233                 String skipHypervisorCheck = null;
234                 if (ctx != null) {
235                         skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK);
236
237                 }
238
239                 // Always perform Hypervisor Status checks
240                 // unless the skip is set to true
241                 if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) {
242
243                         // Check of the Hypervisor for the VM Server is UP and reachable
244                         checkHypervisor(server);
245                 }
246
247                 /*
248                  * Get the image to use. This is determined by the presence or
249                          * absence of snapshot images. If any snapshots exist, then the
250                          * latest snapshot is used, otherwise the image used to construct
251                          * the VM is used.
252                          */
253                         List<Image> snapshots = server.getSnapshots();
254                         String imageToUse;
255                         if (snapshots != null && !snapshots.isEmpty()) {
256                                 imageToUse = snapshots.get(0).getId();
257                         } else {
258                                 imageToUse = server.getImage();
259                                 ImageService imageService = server.getContext().getImageService();
260                 rc.reset();
261                                 try {
262                                         while (rc.attempt()) {
263                                                 try {
264                                                         /*
265                                                          * We are just trying to make sure that the image
266                                                          * exists. We arent interested in the details at
267                                                          * this point.
268                                                          */
269                                                         imageService.getImage(imageToUse);
270                                                         break;
271                                                 } catch (ContextConnectionException e) {
272                                                         msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(),
273                                                                         imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(),
274                                                                         e.getMessage(), Long.toString(rc.getRetryDelay()),
275                                                                         Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
276                                                         logger.error(msg, e);
277                                                         metricsLogger.error(msg);
278                                                         rc.delay();
279                                                 }
280                                         }
281                                 } catch (ZoneException e) {
282                                         msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild");
283                                         generateEvent(rc, false, msg);
284                                         logger.error(msg);
285                                         metricsLogger.error(msg);
286                                         throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
287                                 }
288                         }
289                         if (rc.isFailed()) {
290                                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
291                                 logger.error(msg);
292                                 metricsLogger.error(msg);
293                                 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
294                         }
295                         rc.reset();
296
297         /*
298          * We determine what to do based on the current state of the server
299          */
300         switch (server.getStatus()) {
301             case DELETED:
302                 // Nothing to do, the server is gone
303                 msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(),
304                         server.getTenantId(), "rebuilt");
305                 generateEvent(rc, false, msg);
306                 logger.error(msg);
307                 metricsLogger.error(msg);
308                 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
309
310             case RUNNING:
311                 // Attempt to stop the server, then rebuild it
312                 stopServer(rc, server);
313                 rc.reset();
314                 rebuildServer(rc, server, imageToUse);
315                 rc.reset();
316                 startServer(rc, server);
317                 generateEvent(rc, true, Outcome.SUCCESS.toString());
318                 metricsLogger.info("Server status: RUNNING");
319                 break;
320
321             case ERROR:
322                 msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(),
323                         server.getTenantId(), "rebuild");
324                 generateEvent(rc, false, msg);
325                 logger.error(msg);
326                 metricsLogger.error(msg);
327                 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
328
329             case READY:
330                 // Attempt to rebuild the server
331                 rebuildServer(rc, server, imageToUse);
332                 rc.reset();
333                 startServer(rc, server);
334                 generateEvent(rc, true, Outcome.SUCCESS.toString());
335                 metricsLogger.info("Server status: READY");
336                 break;
337
338             case PAUSED:
339                 // if paused, un-pause it, stop it, and rebuild it
340                 unpauseServer(rc, server);
341                 rc.reset();
342                 stopServer(rc, server);
343                 rc.reset();
344                 rebuildServer(rc, server, imageToUse);
345                 rc.reset();
346                 startServer(rc, server);
347                 generateEvent(rc, true, Outcome.SUCCESS.toString());
348                 metricsLogger.info("Server status: PAUSED");
349                 break;
350
351             case SUSPENDED:
352                 // Attempt to resume the suspended server, stop it, and rebuild it
353                 resumeServer(rc, server);
354                 rc.reset();
355                 stopServer(rc, server);
356                 rc.reset();
357                 rebuildServer(rc, server, imageToUse);
358                 rc.reset();
359                 startServer(rc, server);
360                 generateEvent(rc, true, Outcome.SUCCESS.toString());
361                 metricsLogger.info("Server status: SUSPENDED");
362                 break;
363
364                         default:
365                                 // Hmmm, unknown status, should never occur
366                                 msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(),
367                                                 server.getTenantId(), server.getStatus().name());
368                                 generateEvent(rc, false, msg);
369                                 logger.error(msg);
370                                 metricsLogger.error(msg);
371                                 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
372                         }
373
374
375         }
376
377     /**
378      * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext)
379      */
380     @SuppressWarnings("nls")
381     public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException {
382         Server server = null;
383         RequestContext rc = new RequestContext(ctx);
384         rc.isAlive();
385
386         String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
387         String msg;
388         
389         /*
390          * Set Time for Metrics Logger
391          */
392         long startTime = System.currentTimeMillis();
393         TimeZone tz = TimeZone.getTimeZone("UTC");
394         DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
395         df.setTimeZone(tz);
396         String startTimeStr = df.format(new Date());
397         long endTime = System.currentTimeMillis();
398         long duration = endTime - startTime;
399         String endTimeStr = String.valueOf(endTime);
400         String durationStr = String.valueOf(duration);
401         String endTimeStrUTC = df.format(new Date());
402         MDC.put("EndTimestamp", endTimeStrUTC);
403         MDC.put("ElapsedTime", durationStr);
404         MDC.put("TargetEntity", "cdp");
405         MDC.put("TargetServiceName", "rebuild server");
406         MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
407
408         try {
409             validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL,
410                     ProviderAdapter.PROPERTY_PROVIDER_NAME);
411             String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL);
412
413             VMURL vm = VMURL.parseURL(vm_url);
414             if (validateVM(rc, appName, vm_url, vm)) return null;
415
416             IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
417             String identStr = (ident == null) ? null : ident.toString();
418             ctx.setAttribute("REBUILD_STATUS", "ERROR");
419
420             Context context = null;
421             try {
422                 context = getContext(rc, vm_url, identStr);
423                 if (context != null) {
424                     rc.reset();
425                     server = lookupServer(rc, context, vm.getServerId());
426                     logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString());
427
428                     // Manually checking image service until new PAL release
429                     if (hasImageAccess(rc, context)) {
430                         rebuildServer(rc, server, ctx);
431                         doSuccess(rc);
432                         ctx.setAttribute("REBUILD_STATUS", "SUCCESS");
433                     } else {
434                         msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(),
435                                 "Accessing Image Service Failed");
436                         logger.error(msg);
437                         metricsLogger.error(msg);
438                         doFailure(rc, HttpStatus.FORBIDDEN_403, msg);
439                     }
440                     context.close();
441                 }
442                 else
443                 {
444                     ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND");
445                 }
446             }
447             catch (RequestFailedException e) {
448                 doFailure(rc, e.getStatus(), e.getMessage());
449                 ctx.setAttribute("REBUILD_STATUS", "ERROR");
450             }
451             catch (ResourceNotFoundException e) {
452                 msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url);
453                 ctx.setAttribute("REBUILD_STATUS", "ERROR");
454                 logger.error(msg);
455                 metricsLogger.error(msg);
456                 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
457             } catch (Throwable t) {
458                 msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(),
459                         STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName());
460                 ctx.setAttribute("REBUILD_STATUS", "ERROR");
461                 logger.error(msg, t);
462                 metricsLogger.error(msg);
463                 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
464             }
465         } catch (RequestFailedException e) {
466             doFailure(rc, e.getStatus(), e.getMessage());
467             ctx.setAttribute("REBUILD_STATUS", "ERROR");
468         }
469
470         return server;
471     }
472
473     @Override
474     protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException {
475
476         setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME);
477         logOperation(Msg.REBUILDING_SERVER, params, context);
478         
479         /*
480          * Set Time for Metrics Logger
481          */
482         long startTime = System.currentTimeMillis();
483         TimeZone tz = TimeZone.getTimeZone("UTC");
484         DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
485         df.setTimeZone(tz);
486         String startTimeStr = df.format(new Date());
487         long endTime = System.currentTimeMillis();
488         long duration = endTime - startTime;
489         String endTimeStr = String.valueOf(endTime);
490         String durationStr = String.valueOf(duration);
491         String endTimeStrUTC = df.format(new Date());
492         MDC.put("EndTimestamp", endTimeStrUTC);
493         MDC.put("ElapsedTime", durationStr);
494         MDC.put("TargetEntity", "cdp");
495         MDC.put("TargetServiceName", "rebuild server");
496         MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
497
498         
499         metricsLogger.info("Executing Provider Operation: Rebuild");
500         
501         
502         return rebuildServer(params, context);
503     }
504 }