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.onap.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.onap.appc.Constants;
43 import org.onap.appc.adapter.iaas.ProviderAdapter;
44 import org.onap.appc.adapter.iaas.impl.IdentityURL;
45 import org.onap.appc.adapter.iaas.impl.RequestContext;
46 import org.onap.appc.adapter.iaas.impl.RequestFailedException;
47 import org.onap.appc.adapter.iaas.impl.VMURL;
48 import org.onap.appc.adapter.iaas.provider.operation.common.constants.Property;
49 import org.onap.appc.adapter.iaas.provider.operation.common.enums.Operation;
50 import org.onap.appc.adapter.iaas.provider.operation.common.enums.Outcome;
51 import org.onap.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation;
52 import org.onap.appc.configuration.Configuration;
53 import org.onap.appc.configuration.ConfigurationFactory;
54 import org.onap.appc.exceptions.APPCException;
55 import org.onap.appc.i18n.Msg;
56 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;
64 import static org.onap.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE;
65 import static org.onap.appc.adapter.utils.Constants.ADAPTER_NAME;
67 public class RebuildServer extends ProviderServerOperation {
69 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class);
70 private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
71 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
72 //the sleep time used by thread.sleep to give "some time for OpenStack to start processing the request"
73 private long rebuildSleepTime = 10L * 1000L;
76 * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be
77 * in the correct state to do the rebuild.
79 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
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(rebuildSleepTime);
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, server.getName(), server.getId(),
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 its processing.
155 * @param server The server to be rebuilt
156 * @throws ZoneException When error occurs
157 * @throws RequestFailedException When server status is error
159 @SuppressWarnings("nls")
160 private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx)
161 throws ZoneException, RequestFailedException {
162 ServerBootSource builtFrom = server.getBootSource();
165 * Set Time for Metrics Logger
167 setTimeForMetricsLogger();
170 // Throw exception for non image/snap boot source
171 if (ServerBootSource.VOLUME.equals(builtFrom)) {
172 msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]",
174 generateEvent(rc, false, msg);
176 metricsLogger.error(msg);
177 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server);
181 * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the
182 * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down
183 * to one we can deal with. If not, then we have to fail the request.
185 Context context = server.getContext();
186 Provider provider = context.getProvider();
187 ComputeService service = context.getComputeService();
188 if (server.getStatus().equals(Server.Status.PENDING)) {
190 waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR,
191 Server.Status.SUSPENDED, Server.Status.PAUSED);
194 // Is the skip Hypervisor check attribute populated?
195 String skipHypervisorCheck = configuration.getProperty(Property.SKIP_HYPERVISOR_CHECK);
196 if (skipHypervisorCheck == null && ctx != null) {
197 skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK);
200 // Always perform Hypervisor Status checks
201 // unless the skip is set to true
202 if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) {
203 // Check of the Hypervisor for the VM Server is UP and reachable
204 checkHypervisor(server);
208 * Get the image to use. This is determined by the presence or absence of snapshot images. If any snapshots
209 * exist, then the latest snapshot is used, otherwise the image used to construct the VM is used.
211 List<Image> snapshots = server.getSnapshots();
213 if (snapshots != null && !snapshots.isEmpty()) {
214 imageToUse = snapshots.get(0).getId();
216 imageToUse = server.getImage();
217 ImageService imageService = server.getContext().getImageService();
220 while (rc.attempt()) {
223 * We are just trying to make sure that the image exists. We arent interested in the details at
226 imageService.getImage(imageToUse);
228 } catch (ContextConnectionException e) {
229 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(),
230 imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(),
231 e.getMessage(), Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
232 Integer.toString(rc.getRetryLimit()));
233 logger.error(msg, e);
234 metricsLogger.error(msg);
238 } catch (ZoneException e) {
239 msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild");
240 generateEvent(rc, false, msg);
242 metricsLogger.error(msg);
243 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
247 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
249 metricsLogger.error(msg);
250 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server);
255 * We determine what to do based on the current state of the server
257 switch (server.getStatus()) {
259 // Nothing to do, the server is gone
260 msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(),
261 server.getTenantId(), "rebuilt");
262 generateEvent(rc, false, msg);
264 metricsLogger.error(msg);
265 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
268 // Attempt to stop the server, then rebuild it
269 stopServer(rc, server);
271 rebuildServer(rc, server, imageToUse);
273 startServer(rc, server);
274 generateEvent(rc, true, Outcome.SUCCESS.toString());
275 metricsLogger.info("Server status: RUNNING");
279 msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(),
280 server.getTenantId(), "rebuild");
281 generateEvent(rc, false, msg);
283 metricsLogger.error(msg);
284 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
287 // Attempt to rebuild the server
288 rebuildServer(rc, server, imageToUse);
290 startServer(rc, server);
291 generateEvent(rc, true, Outcome.SUCCESS.toString());
292 metricsLogger.info("Server status: READY");
296 // if paused, un-pause it, stop it, and rebuild it
297 unpauseServer(rc, server);
299 stopServer(rc, server);
301 rebuildServer(rc, server, imageToUse);
303 startServer(rc, server);
304 generateEvent(rc, true, Outcome.SUCCESS.toString());
305 metricsLogger.info("Server status: PAUSED");
309 // Attempt to resume the suspended server, stop it, and rebuild it
310 resumeServer(rc, server);
312 stopServer(rc, server);
314 rebuildServer(rc, server, imageToUse);
316 startServer(rc, server);
317 generateEvent(rc, true, Outcome.SUCCESS.toString());
318 metricsLogger.info("Server status: SUSPENDED");
322 // Hmmm, unknown status, should never occur
323 msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(),
324 server.getTenantId(), server.getStatus().name());
325 generateEvent(rc, false, msg);
327 metricsLogger.error(msg);
328 throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server);
333 * @see org.onap.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map,
334 * org.onap.ccsdk.sli.core.sli.SvcLogicContext)
336 @SuppressWarnings("nls")
337 public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException {
338 Server server = null;
339 RequestContext rc = new RequestContext(ctx);
342 setTimeForMetricsLogger();
346 validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL,
347 ProviderAdapter.PROPERTY_PROVIDER_NAME);
349 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
350 String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL);
351 VMURL vm = VMURL.parseURL(vm_url);
352 if (validateVM(rc, appName, vm_url, vm))
355 IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
356 String identStr = (ident == null) ? null : ident.toString();
357 ctx.setAttribute("REBUILD_STATUS", "ERROR");
359 Context context = null;
360 String tenantName = "Unknown";//to be used also in case of exception
362 context = getContext(rc, vm_url, identStr);
363 if (context != null) {
364 tenantName = context.getTenantName();//this varaible also is used in case of exception
366 server = lookupServer(rc, context, vm.getServerId());
367 logger.debug(Msg.SERVER_FOUND, vm_url, tenantName, server.getStatus().toString());
369 // Manually checking image service until new PAL release
370 if (hasImageAccess(rc, context)) {
371 rebuildServer(rc, server, ctx);
373 ctx.setAttribute("REBUILD_STATUS", "SUCCESS");
375 msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(),
376 "Accessing Image Service Failed");
378 metricsLogger.error(msg);
379 doFailure(rc, HttpStatus.FORBIDDEN_403, msg);
383 ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND");
385 } catch (RequestFailedException e) {
386 doFailure(rc, e.getStatus(), e.getMessage());
387 ctx.setAttribute("REBUILD_STATUS", "ERROR");
388 } catch (ResourceNotFoundException e) {
389 msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url);
390 ctx.setAttribute("REBUILD_STATUS", "ERROR");
392 metricsLogger.error(msg);
393 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
394 } catch (Exception e1) {
395 msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e1, e1.getClass().getSimpleName(),
396 STOP_SERVICE.toString(), vm_url, tenantName);
397 ctx.setAttribute("REBUILD_STATUS", "ERROR");
398 logger.error(msg, e1);
399 metricsLogger.error(msg);
400 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
402 } catch (RequestFailedException e) {
403 doFailure(rc, e.getStatus(), e.getMessage());
404 ctx.setAttribute("REBUILD_STATUS", "ERROR");
411 protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context)
412 throws APPCException {
413 setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME);
414 logOperation(Msg.REBUILDING_SERVER, params, context);
416 setTimeForMetricsLogger();
418 metricsLogger.info("Executing Provider Operation: Rebuild");
420 return rebuildServer(params, context);
423 private void setTimeForMetricsLogger() {
424 long startTime = System.currentTimeMillis();
425 TimeZone tz = TimeZone.getTimeZone("UTC");
426 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
428 long endTime = System.currentTimeMillis();
429 long duration = endTime - startTime;
430 String durationStr = String.valueOf(duration);
431 String endTimeStrUTC = df.format(new Date());
432 MDC.put("EndTimestamp", endTimeStrUTC);
433 MDC.put("ElapsedTime", durationStr);
434 MDC.put("TargetEntity", "cdp");
435 MDC.put("TargetServiceName", "rebuild server");
436 MDC.put("ClassName", "org.onap.appc.adapter.iaas.provider.operation.impl.RebuildServer");
440 * Sets the sleep time used by thread.sleep to give
441 * "some time for OpenStack to start processing the request".
443 * @param millis Time to sleep in milliseconds
445 public void setRebuildSleepTime(long millis){
446 this.rebuildSleepTime = millis;