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.base;
27 import com.att.cdp.exceptions.ContextConnectionException;
28 import com.att.cdp.exceptions.NotLoggedInException;
29 import com.att.cdp.exceptions.TimeoutException;
30 import com.att.cdp.exceptions.ZoneException;
31 import com.att.cdp.pal.util.StringHelper;
32 import com.att.cdp.zones.ComputeService;
33 import com.att.cdp.zones.Context;
34 import com.att.cdp.zones.ImageService;
35 import com.att.cdp.zones.NetworkService;
36 import com.att.cdp.zones.Provider;
37 import com.att.cdp.zones.model.Hypervisor;
38 import com.att.cdp.zones.model.Image;
39 import com.att.cdp.zones.model.Network;
40 import com.att.cdp.zones.model.Port;
41 import com.att.cdp.zones.model.Server;
42 import com.att.eelf.configuration.EELFLogger;
43 import com.att.eelf.configuration.EELFManager;
44 import com.att.eelf.i18n.EELFResourceManager;
45 import java.util.ArrayList;
46 import java.util.List;
47 import org.glassfish.grizzly.http.util.HttpStatus;
48 import org.onap.appc.Constants;
49 import org.onap.appc.adapter.iaas.impl.RequestContext;
50 import org.onap.appc.adapter.iaas.impl.RequestFailedException;
51 import org.onap.appc.i18n.Msg;
54 * @since September 29, 2016
56 public abstract class ProviderServerOperation extends ProviderOperation {
58 private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class);
61 * Looks up the indicated server using the provided context and returns the server to the caller
63 * @param rc The request context
64 * @param context The provider context
65 * @param id The id of the server
66 * @return The server, or null if there is a problem
67 * @throws ZoneException If the server cannot be found
68 * @throws RequestFailedException If the server cannot be found because we cant connect to the provider
70 @SuppressWarnings("nls")
71 protected Server lookupServer(RequestContext rc, Context context, String id)
72 throws ZoneException, RequestFailedException {
73 ComputeService service = context.getComputeService();
76 Provider provider = context.getProvider();
78 while (rc.attempt()) {
80 server = service.getServer(id);
82 } catch (ContextConnectionException e) {
83 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
84 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
85 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
86 Integer.toString(rc.getRetryLimit()));
92 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
94 doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
95 throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server);
102 * Resume a suspended server and wait for it to enter a running state
104 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
105 * @param server The server to be resumed
107 @SuppressWarnings("nls")
108 protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
109 logger.debug(Msg.RESUME_SERVER, server.getId());
111 Context context = server.getContext();
113 Provider provider = context.getProvider();
114 ComputeService service = context.getComputeService();
115 while (rc.attempt()) {
119 } catch (ContextConnectionException e) {
120 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
121 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
122 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
123 Integer.toString(rc.getRetryLimit()));
124 logger.error(msg, e);
129 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
131 throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
134 waitForStateChange(rc, server, Server.Status.RUNNING);
138 protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
139 logger.info("Checking permissions for image service.");
141 ImageService service = context.getImageService();
142 service.getImageByName("CHECK_IMAGE_ACCESS");
143 logger.info("Image service is accessible.");
145 } catch (ZoneException e) {
146 logger.warn("Image service could not be accessed. Some operations may fail.", e);
153 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. <p>
154 * This method checks the state of the server periodically for one of the desired states. When the server enters one
155 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
156 * desired states within the allocated timeout period, then the method returns a failed response (false). No
157 * exceptions are thrown from this method. </p>
159 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
160 * @param image The server to wait on
161 * @param desiredStates A variable list of desired states, any one of which is allowed.
162 * @throws RequestFailedException If the request times out or fails for some reason
164 @SuppressWarnings("nls")
165 protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
166 throws RequestFailedException, NotLoggedInException {
167 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
168 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
169 Context context = image.getContext();
170 Provider provider = context.getProvider();
171 ImageService service = context.getImageService();
174 long endTime = System.currentTimeMillis() + (timeout * 1000); //
176 while (rc.attempt()) {
179 image.waitForStateChange(pollInterval, timeout, desiredStates);
181 } catch (TimeoutException e) {
182 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
183 List<String> list = new ArrayList<>();
184 for (Image.Status desiredState : desiredStates) {
185 list.add(desiredState.name());
187 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
188 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
189 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
190 Integer.toString(rc.getRetryLimit()));
191 logger.error(msg, e);
194 } catch (ZoneException e) {
195 List<String> list = new ArrayList<>();
196 for (Image.Status desiredState : desiredStates) {
197 list.add(desiredState.name());
199 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
200 "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
202 logger.error(reason);
203 logger.error(EELFResourceManager.format(e));
205 // Instead of failing we are going to wait and try again.
206 // Timeout is reduced by delay time
207 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
209 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
210 // throw new RequestFailedException(e, operation, reason,
215 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
217 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
224 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. <p>
225 * This method checks the state of the server periodically for one of the desired states. When the server enters one
226 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
227 * desired states within the allocated timeout period, then the method returns a failed response (false). No
228 * exceptions are thrown from this method. </p>
230 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
231 * @param server The server to wait on
232 * @param desiredStates A variable list of desired states, any one of which is allowed.
233 * @throws RequestFailedException If the request times out or fails for some reason
235 @SuppressWarnings("nls")
236 protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
237 throws RequestFailedException {
238 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
239 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
240 Context context = server.getContext();
241 Provider provider = context.getProvider();
242 ComputeService service = context.getComputeService();
245 long endTime = System.currentTimeMillis() + (timeout * 1000); //
247 while (rc.attempt()) {
250 server.waitForStateChange(pollInterval, timeout, desiredStates);
252 } catch (TimeoutException e) {
253 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
254 List<String> list = new ArrayList<>();
255 for (Server.Status desiredState : desiredStates) {
256 list.add(desiredState.name());
258 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
259 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
260 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
261 Integer.toString(rc.getRetryLimit()));
262 logger.error(msg, e);
265 } catch (ZoneException e) {
266 List<String> list = new ArrayList<>();
267 for (Server.Status desiredState : desiredStates) {
268 list.add(desiredState.name());
270 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
271 "server", server.getName(), server.getId(), StringHelper.asList(list),
272 server.getStatus().name(), e.getMessage());
273 logger.error(reason);
274 logger.error(EELFResourceManager.format(e));
276 // Instead of failing we are going to wait and try again.
277 // Timeout is reduced by delay time
278 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
280 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
281 // throw new RequestFailedException(e, operation, reason,
286 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
288 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
294 * Stop the specified server and wait for it to stop
296 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
297 * @param server The server to be stopped
299 @SuppressWarnings("nls")
300 protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
301 logger.debug(Msg.STOP_SERVER, server.getId());
304 Context context = server.getContext();
305 Provider provider = context.getProvider();
306 ComputeService service = context.getComputeService();
307 while (rc.attempt()) {
311 } catch (ContextConnectionException e) {
312 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
313 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
314 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
315 Integer.toString(rc.getRetryLimit()));
316 logger.error(msg, e);
321 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
323 throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
326 waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
330 * Start the server and wait for it to enter a running state
332 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
333 * @param server The server to be started
335 @SuppressWarnings("nls")
336 protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
337 logger.debug(Msg.START_SERVER, server.getId());
339 Context context = server.getContext();
340 Provider provider = context.getProvider();
341 ComputeService service = context.getComputeService();
342 while (rc.attempt()) {
346 } catch (ContextConnectionException e) {
347 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
348 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
349 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
350 Integer.toString(rc.getRetryLimit()));
351 logger.error(msg, e);
356 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
358 throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
361 waitForStateChange(rc, server, Server.Status.RUNNING);
366 * Un-Pause a paused server and wait for it to enter a running state
368 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
369 * @param server The server to be un-paused
371 @SuppressWarnings("nls")
372 protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
373 logger.debug(Msg.UNPAUSE_SERVER, server.getId());
376 Context context = server.getContext();
377 Provider provider = context.getProvider();
378 ComputeService service = context.getComputeService();
379 while (rc.attempt()) {
383 } catch (ContextConnectionException e) {
384 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
385 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
386 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
387 Integer.toString(rc.getRetryLimit()));
388 logger.error(msg, e);
393 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
395 throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
398 waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
403 * Generates the event indicating what happened
405 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
406 * @param success True if the event represents a successful outcome
407 * @param msg The detailed message
409 protected void generateEvent(@SuppressWarnings("unused") RequestContext rc,
410 @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
411 // indication to the DG to generate the event?
415 * Checks if the VM is connected to the Virtual Network and reachable
417 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
418 * @param server The server object representing the server we want to operate on
419 * @param context The interface cloud service provider to access services or the object model, or both
421 protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
422 throws ZoneException, RequestFailedException {
424 logger.info("Performing the VM Server networking status checks...");
425 List<Port> ports = server.getPorts();
427 NetworkService netSvc = context.getNetworkService();
430 for (Port port : ports) {
431 switch (port.getPortState().toString().toUpperCase()) {
433 /* The port is connected, configured, and usable for communication */
434 Network network = netSvc.getNetworkById(port.getNetwork());
435 validateNetwork(rc, server, port, network);
438 /* The port is disconnected or powered-off and cannot be used for communication */
439 msg = createErrorMessage(rc, server, port);
440 throw new RequestFailedException("VM Server Port status is OFFLINE", msg,
441 HttpStatus.PRECONDITION_FAILED_412, server);
443 /* The port's status is changing because of some event or operation. The final state is yet to be determined. */
444 msg = createErrorMessage(rc, server, port);
445 throw new RequestFailedException("VM Server Port status is PENDING", msg,
446 HttpStatus.PRECONDITION_FAILED_412, server);
448 /* The port is in an unknown state and cannot be used. */
449 msg = createErrorMessage(rc, server, port);
450 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg,
451 HttpStatus.PRECONDITION_FAILED_412, server);
453 logger.error("Invalid port state");
458 logger.info("Passed the VM Server the Hypervisor status checks..");
461 private String createErrorMessage(RequestContext rc, Server server, Port port) {
463 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
465 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
469 private void validateNetwork(RequestContext rc, Server server, Port port, Network network)
470 throws RequestFailedException {
472 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
473 msg = createErrorMessage(rc, server, port);
474 throw new RequestFailedException("VM Server Network is DOWN", msg,
475 HttpStatus.PRECONDITION_FAILED_412, server);
480 * Checks if the VM is connected to the Virtual Network and reachable
482 * @param server The server object representing the server we want to operate on
484 protected void checkHypervisor(Server server) throws ZoneException, RequestFailedException {
486 logger.info("Performing the Hypervisor status checks..");
489 if (server.getHypervisor() != null && server.getHypervisor().getStatus() != null
490 && server.getHypervisor().getState() != null) {
494 status = server.getHypervisor().getStatus().toString();
495 state = server.getHypervisor().getState().toString();
497 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
498 msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(),
501 throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg,
502 HttpStatus.PRECONDITION_FAILED_412, server);
505 msg = EELFResourceManager.format(Msg.HYPERVISOR_STATUS_UKNOWN, server.getName());
508 throw new RequestFailedException("Unable to determine Hypervisor status", msg,
509 HttpStatus.PRECONDITION_FAILED_412, server);
511 logger.info("Passed the Hypervisor status checks..");