2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.openecomp.appc.adapter.iaas.provider.operation.impl;
24 import org.openecomp.appc.Constants;
25 import org.openecomp.appc.adapter.iaas.ProviderAdapter;
26 import org.openecomp.appc.adapter.iaas.impl.IdentityURL;
27 import org.openecomp.appc.adapter.iaas.impl.RequestContext;
28 import org.openecomp.appc.adapter.iaas.impl.RequestFailedException;
29 import org.openecomp.appc.adapter.iaas.impl.VMURL;
30 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation;
31 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome;
32 import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation;
33 import org.openecomp.appc.configuration.Configuration;
34 import org.openecomp.appc.configuration.ConfigurationFactory;
35 import org.openecomp.appc.exceptions.APPCException;
36 import org.openecomp.appc.i18n.Msg;
37 import com.att.cdp.exceptions.ContextConnectionException;
38 import com.att.cdp.exceptions.ResourceNotFoundException;
39 import com.att.cdp.exceptions.ZoneException;
40 import com.att.cdp.zones.ComputeService;
41 import com.att.cdp.zones.Context;
42 import com.att.cdp.zones.ImageService;
43 import com.att.cdp.zones.Provider;
44 import com.att.cdp.zones.model.Image;
45 import com.att.cdp.zones.model.ModelObject;
46 import com.att.cdp.zones.model.Server;
47 import com.att.cdp.zones.model.ServerBootSource;
48 import com.att.eelf.configuration.EELFLogger;
49 import com.att.eelf.configuration.EELFManager;
50 import com.att.eelf.i18n.EELFResourceManager;
51 import org.openecomp.sdnc.sli.SvcLogicContext;
52 import org.glassfish.grizzly.http.util.HttpStatus;
54 import java.util.List;
57 import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE;
58 import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE;
59 import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME;
62 import java.text.DateFormat;
63 import java.text.SimpleDateFormat;
64 import java.util.Date;
65 import java.util.TimeZone;
68 * @since September 26, 2016
70 public class RebuildServer extends ProviderServerOperation {
72 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class);
73 private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
74 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
77 * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be
78 * in the correct state to do the rebuild.
81 * The request context that manages the state and recovery of the request for the life of its processing.
83 * the server to be rebuilt
85 * The image to be used (or snapshot)
86 * @throws RequestFailedException
87 * if the server does not change state in the allotted time
89 @SuppressWarnings("nls")
90 private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException {
91 logger.debug(Msg.REBUILD_SERVER, server.getId());
94 Context context = server.getContext();
95 Provider provider = context.getProvider();
96 ComputeService service = context.getComputeService();
99 * Set Time for Metrics Logger
101 long startTime = System.currentTimeMillis();
102 TimeZone tz = TimeZone.getTimeZone("UTC");
103 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
105 String startTimeStr = df.format(new Date());
106 long endTime = System.currentTimeMillis();
107 long duration = endTime - startTime;
108 String endTimeStr = String.valueOf(endTime);
109 String durationStr = String.valueOf(duration);
110 String endTimeStrUTC = df.format(new Date());
111 MDC.put("EndTimestamp", endTimeStrUTC);
112 MDC.put("ElapsedTime", durationStr);
113 MDC.put("TargetEntity", "cdp");
114 MDC.put("TargetServiceName", "rebuild server");
115 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
118 while (rc.attempt()) {
120 server.rebuild(image);
122 } catch (ContextConnectionException e) {
123 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
124 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
125 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
126 Integer.toString(rc.getRetryLimit()));
127 logger.error(msg, e);
128 metricsLogger.error(msg,e);
134 * We need to provide some time for OpenStack to start processing the request.
137 Thread.sleep(10L * 1000L);
138 } catch (InterruptedException e) {
139 logger.trace("Sleep threw interrupted exception, should never occur");
140 metricsLogger.trace("Sleep threw interrupted exception, should never occur");
142 } catch (ZoneException e) {
144 EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), e.getMessage());
146 metricsLogger.error(msg);
147 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
152 * Once we have started the process, now we wait for the final state of stopped. This should be the final state
153 * (since we started the rebuild with the server stopped).
155 waitForStateChange(rc, server, Server.Status.READY);
158 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
160 metricsLogger.error(msg);
161 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
167 * This method is called to rebuild the provided server.
169 * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding
170 * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose.
174 * The request context that manages the state and recovery of the request for the life of its processing.
176 * @throws ZoneException
177 * @throws RequestFailedException
179 @SuppressWarnings("nls")
180 private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx)
181 throws ZoneException, RequestFailedException {
183 ServerBootSource builtFrom = server.getBootSource();
187 * Set Time for Metrics Logger
189 long startTime = System.currentTimeMillis();
190 TimeZone tz = TimeZone.getTimeZone("UTC");
191 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
193 String startTimeStr = df.format(new Date());
194 long endTime = System.currentTimeMillis();
195 long duration = endTime - startTime;
196 String endTimeStr = String.valueOf(endTime);
197 String durationStr = String.valueOf(duration);
198 String endTimeStrUTC = df.format(new Date());
199 MDC.put("EndTimestamp", endTimeStrUTC);
200 MDC.put("ElapsedTime", durationStr);
201 MDC.put("TargetEntity", "cdp");
202 MDC.put("TargetServiceName", "rebuild server");
203 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
205 // Throw exception for non image/snap boot source
206 if (ServerBootSource.VOLUME.equals(builtFrom)) {
207 msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]",
209 generateEvent(rc, false, msg);
211 metricsLogger.error(msg);
212 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server);
216 * Pending is a bit of a special case. If we find the server is in a
217 * pending state, then the provider is in the process of changing state
218 * of the server. So, lets try to wait a little bit and see if the state
219 * settles down to one we can deal with. If not, then we have to fail
222 Context context = server.getContext();
223 Provider provider = context.getProvider();
224 ComputeService service = context.getComputeService();
225 if (server.getStatus().equals(Server.Status.PENDING)) {
227 waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR,
228 Server.Status.SUSPENDED, Server.Status.PAUSED);
231 // Is the skip Hypervisor check attribute populated?
232 String skipHypervisorCheck = null;
234 skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK);
238 // Always perform Hypervisor Status checks
239 // unless the skip is set to true
240 if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) {
242 // Check of the Hypervisor for the VM Server is UP and reachable
243 checkHypervisor(server);
247 * Get the image to use. This is determined by the presence or
248 * absence of snapshot images. If any snapshots exist, then the
249 * latest snapshot is used, otherwise the image used to construct
252 List<Image> snapshots = server.getSnapshots();
254 if (snapshots != null && !snapshots.isEmpty()) {
255 imageToUse = snapshots.get(0).getId();
257 imageToUse = server.getImage();
258 ImageService imageService = server.getContext().getImageService();
261 while (rc.attempt()) {
264 * We are just trying to make sure that the image
265 * exists. We arent interested in the details at
268 imageService.getImage(imageToUse);
270 } catch (ContextConnectionException e) {
271 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(),
272 imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(),
273 e.getMessage(), Long.toString(rc.getRetryDelay()),
274 Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
275 logger.error(msg, e);
276 metricsLogger.error(msg);
280 } catch (ZoneException e) {
281 msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild");
282 generateEvent(rc, false, msg);
284 metricsLogger.error(msg);
285 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
289 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
291 metricsLogger.error(msg);
292 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
297 * We determine what to do based on the current state of the server
299 switch (server.getStatus()) {
301 // Nothing to do, the server is gone
302 msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(),
303 server.getTenantId(), "rebuilt");
304 generateEvent(rc, false, msg);
306 metricsLogger.error(msg);
307 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
310 // Attempt to stop the server, then rebuild it
311 stopServer(rc, server);
313 rebuildServer(rc, server, imageToUse);
315 startServer(rc, server);
316 generateEvent(rc, true, Outcome.SUCCESS.toString());
317 metricsLogger.info("Server status: RUNNING");
321 msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(),
322 server.getTenantId(), "rebuild");
323 generateEvent(rc, false, msg);
325 metricsLogger.error(msg);
326 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
329 // Attempt to rebuild the server
330 rebuildServer(rc, server, imageToUse);
332 startServer(rc, server);
333 generateEvent(rc, true, Outcome.SUCCESS.toString());
334 metricsLogger.info("Server status: READY");
338 // if paused, un-pause it, stop it, and rebuild it
339 unpauseServer(rc, server);
341 stopServer(rc, server);
343 rebuildServer(rc, server, imageToUse);
345 startServer(rc, server);
346 generateEvent(rc, true, Outcome.SUCCESS.toString());
347 metricsLogger.info("Server status: PAUSED");
351 // Attempt to resume the suspended server, stop it, and rebuild it
352 resumeServer(rc, server);
354 stopServer(rc, server);
356 rebuildServer(rc, server, imageToUse);
358 startServer(rc, server);
359 generateEvent(rc, true, Outcome.SUCCESS.toString());
360 metricsLogger.info("Server status: SUSPENDED");
364 // Hmmm, unknown status, should never occur
365 msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(),
366 server.getTenantId(), server.getStatus().name());
367 generateEvent(rc, false, msg);
369 metricsLogger.error(msg);
370 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
377 * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext)
379 @SuppressWarnings("nls")
380 public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException {
381 Server server = null;
382 RequestContext rc = new RequestContext(ctx);
385 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
389 * Set Time for Metrics Logger
391 long startTime = System.currentTimeMillis();
392 TimeZone tz = TimeZone.getTimeZone("UTC");
393 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
395 String startTimeStr = df.format(new Date());
396 long endTime = System.currentTimeMillis();
397 long duration = endTime - startTime;
398 String endTimeStr = String.valueOf(endTime);
399 String durationStr = String.valueOf(duration);
400 String endTimeStrUTC = df.format(new Date());
401 MDC.put("EndTimestamp", endTimeStrUTC);
402 MDC.put("ElapsedTime", durationStr);
403 MDC.put("TargetEntity", "cdp");
404 MDC.put("TargetServiceName", "rebuild server");
405 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
408 validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL,
409 ProviderAdapter.PROPERTY_PROVIDER_NAME);
410 String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL);
412 VMURL vm = VMURL.parseURL(vm_url);
413 if (validateVM(rc, appName, vm_url, vm)) return null;
415 IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
416 String identStr = (ident == null) ? null : ident.toString();
417 ctx.setAttribute("REBUILD_STATUS", "ERROR");
419 Context context = null;
421 context = getContext(rc, vm_url, identStr);
422 if (context != null) {
424 server = lookupServer(rc, context, vm.getServerId());
425 logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString());
427 // Manually checking image service until new PAL release
428 if (hasImageAccess(rc, context)) {
429 rebuildServer(rc, server, ctx);
431 ctx.setAttribute("REBUILD_STATUS", "SUCCESS");
433 msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(),
434 "Accessing Image Service Failed");
436 metricsLogger.error(msg);
437 doFailure(rc, HttpStatus.FORBIDDEN_403, msg);
443 ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND");
446 catch (RequestFailedException e) {
447 doFailure(rc, e.getStatus(), e.getMessage());
448 ctx.setAttribute("REBUILD_STATUS", "ERROR");
450 catch (ResourceNotFoundException e) {
451 msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url);
452 ctx.setAttribute("REBUILD_STATUS", "ERROR");
454 metricsLogger.error(msg);
455 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
456 } catch (Throwable t) {
457 msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(),
458 STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName());
459 ctx.setAttribute("REBUILD_STATUS", "ERROR");
460 logger.error(msg, t);
461 metricsLogger.error(msg);
462 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
464 } catch (RequestFailedException e) {
465 doFailure(rc, e.getStatus(), e.getMessage());
466 ctx.setAttribute("REBUILD_STATUS", "ERROR");
473 protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException {
475 setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME);
476 logOperation(Msg.REBUILDING_SERVER, params, context);
479 * Set Time for Metrics Logger
481 long startTime = System.currentTimeMillis();
482 TimeZone tz = TimeZone.getTimeZone("UTC");
483 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
485 String startTimeStr = df.format(new Date());
486 long endTime = System.currentTimeMillis();
487 long duration = endTime - startTime;
488 String endTimeStr = String.valueOf(endTime);
489 String durationStr = String.valueOf(duration);
490 String endTimeStrUTC = df.format(new Date());
491 MDC.put("EndTimestamp", endTimeStrUTC);
492 MDC.put("ElapsedTime", durationStr);
493 MDC.put("TargetEntity", "cdp");
494 MDC.put("TargetServiceName", "rebuild server");
495 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");
498 metricsLogger.info("Executing Provider Operation: Rebuild");
501 return rebuildServer(params, context);