2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.appc.adapter.iaas.provider.operation.impl;
27 import org.openecomp.appc.Constants;
28 import org.openecomp.appc.adapter.iaas.ProviderAdapter;
29 import org.openecomp.appc.adapter.iaas.impl.IdentityURL;
30 import org.openecomp.appc.adapter.iaas.impl.RequestContext;
31 import org.openecomp.appc.adapter.iaas.impl.RequestFailedException;
32 import org.openecomp.appc.adapter.iaas.impl.VMURL;
33 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation;
34 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome;
35 import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation;
36 import org.openecomp.appc.configuration.Configuration;
37 import org.openecomp.appc.configuration.ConfigurationFactory;
38 import org.openecomp.appc.exceptions.APPCException;
39 import org.openecomp.appc.i18n.Msg;
40 import com.att.cdp.exceptions.ContextConnectionException;
41 import com.att.cdp.exceptions.ResourceNotFoundException;
42 import com.att.cdp.exceptions.ZoneException;
43 import com.att.cdp.zones.ComputeService;
44 import com.att.cdp.zones.Context;
45 import com.att.cdp.zones.ImageService;
46 import com.att.cdp.zones.Provider;
47 import com.att.cdp.zones.model.Image;
48 import com.att.cdp.zones.model.ModelObject;
49 import com.att.cdp.zones.model.Server;
50 import com.att.cdp.zones.model.ServerBootSource;
51 import com.att.eelf.configuration.EELFLogger;
52 import com.att.eelf.configuration.EELFManager;
53 import com.att.eelf.i18n.EELFResourceManager;
54 import org.openecomp.sdnc.sli.SvcLogicContext;
55 import org.glassfish.grizzly.http.util.HttpStatus;
57 import java.util.List;
60 import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE;
61 import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE;
62 import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME;
65 import java.text.DateFormat;
66 import java.text.SimpleDateFormat;
67 import java.util.Date;
68 import java.util.TimeZone;
71 * @since September 26, 2016
73 public class RebuildServer extends ProviderServerOperation {
75 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class);
76 private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
77 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
80 * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be
81 * in the correct state to do the rebuild.
84 * The request context that manages the state and recovery of the request for the life of its processing.
86 * the server to be rebuilt
88 * The image to be used (or snapshot)
89 * @throws RequestFailedException
90 * if the server does not change state in the allotted time
92 @SuppressWarnings("nls")
93 private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException {
94 logger.debug(Msg.REBUILD_SERVER, server.getId());
97 Context context = server.getContext();
98 Provider provider = context.getProvider();
99 ComputeService service = context.getComputeService();
102 * Set Time for Metrics Logger
104 long startTime = System.currentTimeMillis();
105 TimeZone tz = TimeZone.getTimeZone("UTC");
106 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
108 String startTimeStr = df.format(new Date());
109 long endTime = System.currentTimeMillis();
110 long duration = endTime - startTime;
111 String endTimeStr = String.valueOf(endTime);
112 String durationStr = String.valueOf(duration);
113 String endTimeStrUTC = df.format(new Date());
114 MDC.put("EndTimestamp", endTimeStrUTC);
115 MDC.put("ElapsedTime", durationStr);
116 MDC.put("TargetEntity", "cdp");
117 MDC.put("TargetServiceName", "rebuild server");
118 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
121 while (rc.attempt()) {
123 server.rebuild(image);
125 } catch (ContextConnectionException e) {
126 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
127 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
128 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
129 Integer.toString(rc.getRetryLimit()));
130 logger.error(msg, e);
131 metricsLogger.error(msg,e);
137 * We need to provide some time for OpenStack to start processing the request.
140 Thread.sleep(10L * 1000L);
141 } catch (InterruptedException e) {
142 logger.trace("Sleep threw interrupted exception, should never occur");
143 metricsLogger.trace("Sleep threw interrupted exception, should never occur");
145 } catch (ZoneException e) {
147 EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), e.getMessage());
149 metricsLogger.error(msg);
150 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
155 * Once we have started the process, now we wait for the final state of stopped. This should be the final state
156 * (since we started the rebuild with the server stopped).
158 waitForStateChange(rc, server, Server.Status.READY);
161 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
163 metricsLogger.error(msg);
164 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
170 * This method is called to rebuild the provided server.
172 * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding
173 * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose.
177 * The request context that manages the state and recovery of the request for the life of its processing.
179 * @throws ZoneException
180 * @throws RequestFailedException
182 @SuppressWarnings("nls")
183 private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx)
184 throws ZoneException, RequestFailedException {
186 ServerBootSource builtFrom = server.getBootSource();
190 * Set Time for Metrics Logger
192 long startTime = System.currentTimeMillis();
193 TimeZone tz = TimeZone.getTimeZone("UTC");
194 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
196 String startTimeStr = df.format(new Date());
197 long endTime = System.currentTimeMillis();
198 long duration = endTime - startTime;
199 String endTimeStr = String.valueOf(endTime);
200 String durationStr = String.valueOf(duration);
201 String endTimeStrUTC = df.format(new Date());
202 MDC.put("EndTimestamp", endTimeStrUTC);
203 MDC.put("ElapsedTime", durationStr);
204 MDC.put("TargetEntity", "cdp");
205 MDC.put("TargetServiceName", "rebuild server");
206 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
208 // Throw exception for non image/snap boot source
209 if (ServerBootSource.VOLUME.equals(builtFrom)) {
210 msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]",
212 generateEvent(rc, false, msg);
214 metricsLogger.error(msg);
215 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server);
219 * Pending is a bit of a special case. If we find the server is in a
220 * pending state, then the provider is in the process of changing state
221 * of the server. So, lets try to wait a little bit and see if the state
222 * settles down to one we can deal with. If not, then we have to fail
225 Context context = server.getContext();
226 Provider provider = context.getProvider();
227 ComputeService service = context.getComputeService();
228 if (server.getStatus().equals(Server.Status.PENDING)) {
230 waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR,
231 Server.Status.SUSPENDED, Server.Status.PAUSED);
234 // Is the skip Hypervisor check attribute populated?
235 String skipHypervisorCheck = null;
237 skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK);
241 // Always perform Hypervisor Status checks
242 // unless the skip is set to true
243 if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) {
245 // Check of the Hypervisor for the VM Server is UP and reachable
246 checkHypervisor(server);
250 * Get the image to use. This is determined by the presence or
251 * absence of snapshot images. If any snapshots exist, then the
252 * latest snapshot is used, otherwise the image used to construct
255 List<Image> snapshots = server.getSnapshots();
257 if (snapshots != null && !snapshots.isEmpty()) {
258 imageToUse = snapshots.get(0).getId();
260 imageToUse = server.getImage();
261 ImageService imageService = server.getContext().getImageService();
264 while (rc.attempt()) {
267 * We are just trying to make sure that the image
268 * exists. We arent interested in the details at
271 imageService.getImage(imageToUse);
273 } catch (ContextConnectionException e) {
274 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(),
275 imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(),
276 e.getMessage(), Long.toString(rc.getRetryDelay()),
277 Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
278 logger.error(msg, e);
279 metricsLogger.error(msg);
283 } catch (ZoneException e) {
284 msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild");
285 generateEvent(rc, false, msg);
287 metricsLogger.error(msg);
288 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
292 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
294 metricsLogger.error(msg);
295 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
300 * We determine what to do based on the current state of the server
302 switch (server.getStatus()) {
304 // Nothing to do, the server is gone
305 msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(),
306 server.getTenantId(), "rebuilt");
307 generateEvent(rc, false, msg);
309 metricsLogger.error(msg);
310 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
313 // Attempt to stop the server, then rebuild it
314 stopServer(rc, server);
316 rebuildServer(rc, server, imageToUse);
318 startServer(rc, server);
319 generateEvent(rc, true, Outcome.SUCCESS.toString());
320 metricsLogger.info("Server status: RUNNING");
324 msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(),
325 server.getTenantId(), "rebuild");
326 generateEvent(rc, false, msg);
328 metricsLogger.error(msg);
329 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
332 // Attempt to rebuild the server
333 rebuildServer(rc, server, imageToUse);
335 startServer(rc, server);
336 generateEvent(rc, true, Outcome.SUCCESS.toString());
337 metricsLogger.info("Server status: READY");
341 // if paused, un-pause it, stop it, and rebuild it
342 unpauseServer(rc, server);
344 stopServer(rc, server);
346 rebuildServer(rc, server, imageToUse);
348 startServer(rc, server);
349 generateEvent(rc, true, Outcome.SUCCESS.toString());
350 metricsLogger.info("Server status: PAUSED");
354 // Attempt to resume the suspended server, stop it, and rebuild it
355 resumeServer(rc, server);
357 stopServer(rc, server);
359 rebuildServer(rc, server, imageToUse);
361 startServer(rc, server);
362 generateEvent(rc, true, Outcome.SUCCESS.toString());
363 metricsLogger.info("Server status: SUSPENDED");
367 // Hmmm, unknown status, should never occur
368 msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(),
369 server.getTenantId(), server.getStatus().name());
370 generateEvent(rc, false, msg);
372 metricsLogger.error(msg);
373 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
380 * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext)
382 @SuppressWarnings("nls")
383 public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException {
384 Server server = null;
385 RequestContext rc = new RequestContext(ctx);
388 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
392 * Set Time for Metrics Logger
394 long startTime = System.currentTimeMillis();
395 TimeZone tz = TimeZone.getTimeZone("UTC");
396 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
398 String startTimeStr = df.format(new Date());
399 long endTime = System.currentTimeMillis();
400 long duration = endTime - startTime;
401 String endTimeStr = String.valueOf(endTime);
402 String durationStr = String.valueOf(duration);
403 String endTimeStrUTC = df.format(new Date());
404 MDC.put("EndTimestamp", endTimeStrUTC);
405 MDC.put("ElapsedTime", durationStr);
406 MDC.put("TargetEntity", "cdp");
407 MDC.put("TargetServiceName", "rebuild server");
408 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
411 validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL,
412 ProviderAdapter.PROPERTY_PROVIDER_NAME);
413 String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL);
415 VMURL vm = VMURL.parseURL(vm_url);
416 if (validateVM(rc, appName, vm_url, vm)) return null;
418 IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
419 String identStr = (ident == null) ? null : ident.toString();
420 ctx.setAttribute("REBUILD_STATUS", "ERROR");
422 Context context = null;
424 context = getContext(rc, vm_url, identStr);
425 if (context != null) {
427 server = lookupServer(rc, context, vm.getServerId());
428 logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString());
430 // Manually checking image service until new PAL release
431 if (hasImageAccess(rc, context)) {
432 rebuildServer(rc, server, ctx);
434 ctx.setAttribute("REBUILD_STATUS", "SUCCESS");
436 msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(),
437 "Accessing Image Service Failed");
439 metricsLogger.error(msg);
440 doFailure(rc, HttpStatus.FORBIDDEN_403, msg);
446 ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND");
449 catch (RequestFailedException e) {
450 doFailure(rc, e.getStatus(), e.getMessage());
451 ctx.setAttribute("REBUILD_STATUS", "ERROR");
453 catch (ResourceNotFoundException e) {
454 msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url);
455 ctx.setAttribute("REBUILD_STATUS", "ERROR");
457 metricsLogger.error(msg);
458 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
459 } catch (Throwable t) {
460 msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(),
461 STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName());
462 ctx.setAttribute("REBUILD_STATUS", "ERROR");
463 logger.error(msg, t);
464 metricsLogger.error(msg);
465 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
467 } catch (RequestFailedException e) {
468 doFailure(rc, e.getStatus(), e.getMessage());
469 ctx.setAttribute("REBUILD_STATUS", "ERROR");
476 protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException {
478 setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME);
479 logOperation(Msg.REBUILDING_SERVER, params, context);
482 * Set Time for Metrics Logger
484 long startTime = System.currentTimeMillis();
485 TimeZone tz = TimeZone.getTimeZone("UTC");
486 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
488 String startTimeStr = df.format(new Date());
489 long endTime = System.currentTimeMillis();
490 long duration = endTime - startTime;
491 String endTimeStr = String.valueOf(endTime);
492 String durationStr = String.valueOf(duration);
493 String endTimeStrUTC = df.format(new Date());
494 MDC.put("EndTimestamp", endTimeStrUTC);
495 MDC.put("ElapsedTime", durationStr);
496 MDC.put("TargetEntity", "cdp");
497 MDC.put("TargetServiceName", "rebuild server");
498 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
501 metricsLogger.info("Executing Provider Operation: Rebuild");
504 return rebuildServer(params, context);