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 com.att.cdp.exceptions.ContextConnectionException;
28 import com.att.cdp.exceptions.ResourceNotFoundException;
29 import com.att.cdp.exceptions.ZoneException;
30 import com.att.cdp.zones.ComputeService;
31 import com.att.cdp.zones.Context;
32 import com.att.cdp.zones.ImageService;
33 import com.att.cdp.zones.Provider;
34 import com.att.cdp.zones.model.Image;
35 import com.att.cdp.zones.model.ModelObject;
36 import com.att.cdp.zones.model.Server;
37 import com.att.cdp.zones.model.ServerBootSource;
38 import com.att.eelf.configuration.EELFLogger;
39 import com.att.eelf.configuration.EELFManager;
40 import com.att.eelf.i18n.EELFResourceManager;
41 import org.glassfish.grizzly.http.util.HttpStatus;
42 import org.openecomp.appc.Constants;
43 import org.openecomp.appc.adapter.iaas.ProviderAdapter;
44 import org.openecomp.appc.adapter.iaas.impl.IdentityURL;
45 import org.openecomp.appc.adapter.iaas.impl.RequestContext;
46 import org.openecomp.appc.adapter.iaas.impl.RequestFailedException;
47 import org.openecomp.appc.adapter.iaas.impl.VMURL;
48 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation;
49 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome;
50 import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation;
51 import org.openecomp.appc.configuration.Configuration;
52 import org.openecomp.appc.configuration.ConfigurationFactory;
53 import org.openecomp.appc.exceptions.APPCException;
54 import org.openecomp.appc.i18n.Msg;
55 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
58 import java.text.DateFormat;
59 import java.text.SimpleDateFormat;
60 import java.util.Date;
61 import java.util.List;
63 import java.util.TimeZone;
65 import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE;
66 import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME;
68 public class RebuildServer extends ProviderServerOperation {
70 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class);
71 private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
72 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
75 * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be
76 * in the correct state to do the rebuild.
78 * @param rc The request context that manages the state and recovery of the request for the life of
80 * @param server the server to be rebuilt
81 * @param image The image to be used (or snapshot)
82 * @throws RequestFailedException if the server does not change state in the allotted time
84 @SuppressWarnings("nls")
85 private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException {
86 logger.debug(Msg.REBUILD_SERVER, server.getId());
89 Context context = server.getContext();
90 Provider provider = context.getProvider();
91 ComputeService service = context.getComputeService();
94 * Set Time for Metrics Logger
96 setTimeForMetricsLogger();
99 while (rc.attempt()) {
101 server.rebuild(image);
103 } catch (ContextConnectionException e) {
104 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
105 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
106 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
107 Integer.toString(rc.getRetryLimit()));
108 logger.error(msg, e);
109 metricsLogger.error(msg, e);
115 * We need to provide some time for OpenStack to start processing the request.
118 Thread.sleep(10L * 1000L);
119 } catch (InterruptedException e) {
120 logger.trace("Sleep threw interrupted exception, should never occur");
121 metricsLogger.trace("Sleep threw interrupted exception, should never occur");
123 } catch (ZoneException e) {
124 msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED,
125 server.getName(), server.getId(), e.getMessage());
127 metricsLogger.error(msg);
128 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
133 * Once we have started the process, now we wait for the final state of stopped. This should be the final state
134 * (since we started the rebuild with the server stopped).
136 waitForStateChange(rc, server, Server.Status.READY);
139 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
141 metricsLogger.error(msg);
142 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
148 * This method is called to rebuild the provided server.
150 * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding
151 * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose.
154 * @param rc The request context that manages the state and recovery of the request for the life of
156 * @param server The server to be rebuilt
157 * @throws ZoneException When error occurs
158 * @throws RequestFailedException When server status is error
160 @SuppressWarnings("nls")
161 private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx)
162 throws ZoneException, RequestFailedException {
163 ServerBootSource builtFrom = server.getBootSource();
166 * Set Time for Metrics Logger
168 setTimeForMetricsLogger();
171 // Throw exception for non image/snap boot source
172 if (ServerBootSource.VOLUME.equals(builtFrom)) {
173 msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]",
175 generateEvent(rc, false, msg);
177 metricsLogger.error(msg);
178 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server);
182 * Pending is a bit of a special case. If we find the server is in a
183 * pending state, then the provider is in the process of changing state
184 * of the server. So, lets try to wait a little bit and see if the state
185 * settles down to one we can deal with. If not, then we have to fail
188 Context context = server.getContext();
189 Provider provider = context.getProvider();
190 ComputeService service = context.getComputeService();
191 if (server.getStatus().equals(Server.Status.PENDING)) {
193 waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR,
194 Server.Status.SUSPENDED, Server.Status.PAUSED);
197 // Is the skip Hypervisor check attribute populated?
198 String skipHypervisorCheck = null;
200 skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK);
203 // Always perform Hypervisor Status checks
204 // unless the skip is set to true
205 if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) {
206 // Check of the Hypervisor for the VM Server is UP and reachable
207 checkHypervisor(server);
211 * Get the image to use. This is determined by the presence or
212 * absence of snapshot images. If any snapshots exist, then the
213 * latest snapshot is used, otherwise the image used to construct
216 List<Image> snapshots = server.getSnapshots();
218 if (snapshots != null && !snapshots.isEmpty()) {
219 imageToUse = snapshots.get(0).getId();
221 imageToUse = server.getImage();
222 ImageService imageService = server.getContext().getImageService();
225 while (rc.attempt()) {
228 * We are just trying to make sure that the image exists.
229 * We arent interested in the details at this point.
231 imageService.getImage(imageToUse);
233 } catch (ContextConnectionException e) {
234 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(),
235 imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(),
236 e.getMessage(), Long.toString(rc.getRetryDelay()),
237 Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
238 logger.error(msg, e);
239 metricsLogger.error(msg);
243 } catch (ZoneException e) {
244 msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild");
245 generateEvent(rc, false, msg);
247 metricsLogger.error(msg);
248 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
252 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
254 metricsLogger.error(msg);
255 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
260 * We determine what to do based on the current state of the server
262 switch (server.getStatus()) {
264 // Nothing to do, the server is gone
265 msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(),
266 server.getTenantId(), "rebuilt");
267 generateEvent(rc, false, msg);
269 metricsLogger.error(msg);
270 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
273 // Attempt to stop the server, then rebuild it
274 stopServer(rc, server);
276 rebuildServer(rc, server, imageToUse);
278 startServer(rc, server);
279 generateEvent(rc, true, Outcome.SUCCESS.toString());
280 metricsLogger.info("Server status: RUNNING");
284 msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(),
285 server.getTenantId(), "rebuild");
286 generateEvent(rc, false, msg);
288 metricsLogger.error(msg);
289 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
292 // Attempt to rebuild the server
293 rebuildServer(rc, server, imageToUse);
295 startServer(rc, server);
296 generateEvent(rc, true, Outcome.SUCCESS.toString());
297 metricsLogger.info("Server status: READY");
301 // if paused, un-pause it, stop it, and rebuild it
302 unpauseServer(rc, server);
304 stopServer(rc, server);
306 rebuildServer(rc, server, imageToUse);
308 startServer(rc, server);
309 generateEvent(rc, true, Outcome.SUCCESS.toString());
310 metricsLogger.info("Server status: PAUSED");
314 // Attempt to resume the suspended server, stop it, and rebuild it
315 resumeServer(rc, server);
317 stopServer(rc, server);
319 rebuildServer(rc, server, imageToUse);
321 startServer(rc, server);
322 generateEvent(rc, true, Outcome.SUCCESS.toString());
323 metricsLogger.info("Server status: SUSPENDED");
327 // Hmmm, unknown status, should never occur
328 msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(),
329 server.getTenantId(), server.getStatus().name());
330 generateEvent(rc, false, msg);
332 metricsLogger.error(msg);
333 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
338 * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext)
340 @SuppressWarnings("nls")
341 public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException {
342 Server server = null;
343 RequestContext rc = new RequestContext(ctx);
346 setTimeForMetricsLogger();
350 validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL,
351 ProviderAdapter.PROPERTY_PROVIDER_NAME);
353 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
354 String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL);
355 VMURL vm = VMURL.parseURL(vm_url);
356 if (validateVM(rc, appName, vm_url, vm)) return null;
358 IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
359 String identStr = (ident == null) ? null : ident.toString();
360 ctx.setAttribute("REBUILD_STATUS", "ERROR");
362 Context context = null;
364 context = getContext(rc, vm_url, identStr);
365 if (context != null) {
367 server = lookupServer(rc, context, vm.getServerId());
368 logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString());
370 // Manually checking image service until new PAL release
371 if (hasImageAccess(rc, context)) {
372 rebuildServer(rc, server, ctx);
374 ctx.setAttribute("REBUILD_STATUS", "SUCCESS");
376 msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED,
377 server.getName(), server.getId(), "Accessing Image Service Failed");
379 metricsLogger.error(msg);
380 doFailure(rc, HttpStatus.FORBIDDEN_403, msg);
384 ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND");
386 } catch (RequestFailedException e) {
387 doFailure(rc, e.getStatus(), e.getMessage());
388 ctx.setAttribute("REBUILD_STATUS", "ERROR");
389 } catch (ResourceNotFoundException e) {
390 msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url);
391 ctx.setAttribute("REBUILD_STATUS", "ERROR");
393 metricsLogger.error(msg);
394 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
395 } catch (Exception e1) {
396 msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e1, e1.getClass().getSimpleName(),
397 STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName());
398 ctx.setAttribute("REBUILD_STATUS", "ERROR");
399 logger.error(msg, e1);
400 metricsLogger.error(msg);
401 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
403 } catch (RequestFailedException e) {
404 doFailure(rc, e.getStatus(), e.getMessage());
405 ctx.setAttribute("REBUILD_STATUS", "ERROR");
412 protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context)
413 throws APPCException {
414 setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME);
415 logOperation(Msg.REBUILDING_SERVER, params, context);
417 setTimeForMetricsLogger();
419 metricsLogger.info("Executing Provider Operation: Rebuild");
421 return rebuildServer(params, context);
424 private void setTimeForMetricsLogger() {
425 long startTime = System.currentTimeMillis();
426 TimeZone tz = TimeZone.getTimeZone("UTC");
427 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
429 long endTime = System.currentTimeMillis();
430 long duration = endTime - startTime;
431 String durationStr = String.valueOf(duration);
432 String endTimeStrUTC = df.format(new Date());
433 MDC.put("EndTimestamp", endTimeStrUTC);
434 MDC.put("ElapsedTime", durationStr);
435 MDC.put("TargetEntity", "cdp");
436 MDC.put("TargetServiceName", "rebuild server");
437 MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer");