2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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 * ============LICENSE_END=========================================================
24 package org.onap.appc.adapter.iaas.provider.operation.impl.base;
26 import com.att.cdp.exceptions.ContextConnectionException;
27 import com.att.cdp.exceptions.NotLoggedInException;
28 import com.att.cdp.exceptions.TimeoutException;
29 import com.att.cdp.exceptions.ZoneException;
30 import com.att.cdp.pal.util.StringHelper;
31 import com.att.cdp.zones.ComputeService;
32 import com.att.cdp.zones.Context;
33 import com.att.cdp.zones.ImageService;
34 import com.att.cdp.zones.NetworkService;
35 import com.att.cdp.zones.Provider;
36 import com.att.cdp.zones.model.Hypervisor;
37 import com.att.cdp.zones.model.Image;
38 import com.att.cdp.zones.model.Network;
39 import com.att.cdp.zones.model.Port;
40 import com.att.cdp.zones.model.Server;
41 import com.att.eelf.configuration.EELFLogger;
42 import com.att.eelf.configuration.EELFManager;
43 import com.att.eelf.i18n.EELFResourceManager;
44 import java.util.ArrayList;
45 import java.util.List;
46 import org.glassfish.grizzly.http.util.HttpStatus;
47 import org.onap.appc.Constants;
48 import org.onap.appc.adapter.iaas.impl.RequestContext;
49 import org.onap.appc.adapter.iaas.impl.RequestFailedException;
50 import org.onap.appc.i18n.Msg;
53 * @since September 29, 2016
55 public abstract class ProviderServerOperation extends ProviderOperation {
57 private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class);
60 * Looks up the indicated server using the provided context and returns the server to the caller
62 * @param rc The request context
63 * @param context The provider context
64 * @param id The id of the server
65 * @return The server, or null if there is a problem
66 * @throws ZoneException If the server cannot be found
67 * @throws RequestFailedException If the server cannot be found because we cant connect to the provider
69 @SuppressWarnings("nls")
70 protected Server lookupServer(RequestContext rc, Context context, String id)
71 throws ZoneException, RequestFailedException {
72 ComputeService service = context.getComputeService();
75 Provider provider = context.getProvider();
77 while (rc.attempt()) {
79 server = service.getServer(id);
81 } catch (ContextConnectionException e) {
82 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
83 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
84 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
85 Integer.toString(rc.getRetryLimit()));
91 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
93 doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
94 throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server);
101 * Resume a suspended server and wait for it to enter a running state
103 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
104 * @param server The server to be resumed
106 @SuppressWarnings("nls")
107 protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
108 logger.debug(Msg.RESUME_SERVER, server.getId());
110 Context context = server.getContext();
112 Provider provider = context.getProvider();
113 ComputeService service = context.getComputeService();
114 while (rc.attempt()) {
118 } catch (ContextConnectionException e) {
119 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
120 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
121 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
122 Integer.toString(rc.getRetryLimit()));
123 logger.error(msg, e);
128 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
130 throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
133 waitForStateChange(rc, server, Server.Status.RUNNING);
137 protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
138 logger.info("Checking permissions for image service.");
140 ImageService service = context.getImageService();
141 service.getImageByName("CHECK_IMAGE_ACCESS");
142 logger.info("Image service is accessible.");
144 } catch (ZoneException e) {
145 logger.warn("Image service could not be accessed. Some operations may fail.", e);
152 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. <p>
153 * This method checks the state of the server periodically for one of the desired states. When the server enters one
154 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
155 * desired states within the allocated timeout period, then the method returns a failed response (false). No
156 * exceptions are thrown from this method. </p>
158 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
159 * @param image The server to wait on
160 * @param desiredStates A variable list of desired states, any one of which is allowed.
161 * @throws RequestFailedException If the request times out or fails for some reason
163 @SuppressWarnings("nls")
164 protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
165 throws RequestFailedException, NotLoggedInException {
166 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
167 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
168 Context context = image.getContext();
169 Provider provider = context.getProvider();
170 ImageService service = context.getImageService();
173 long endTime = System.currentTimeMillis() + (timeout * 1000); //
175 while (rc.attempt()) {
178 image.waitForStateChange(pollInterval, timeout, desiredStates);
180 } catch (TimeoutException e) {
181 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
182 List<String> list = new ArrayList<>();
183 for (Image.Status desiredState : desiredStates) {
184 list.add(desiredState.name());
186 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
187 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
188 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
189 Integer.toString(rc.getRetryLimit()));
190 logger.error(msg, e);
193 } catch (ZoneException e) {
194 List<String> list = new ArrayList<>();
195 for (Image.Status desiredState : desiredStates) {
196 list.add(desiredState.name());
198 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
199 "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
201 logger.error(reason);
202 logger.error(EELFResourceManager.format(e));
204 // Instead of failing we are going to wait and try again.
205 // Timeout is reduced by delay time
206 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
208 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
209 // throw new RequestFailedException(e, operation, reason,
214 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
216 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
223 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. <p>
224 * This method checks the state of the server periodically for one of the desired states. When the server enters one
225 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
226 * desired states within the allocated timeout period, then the method returns a failed response (false). No
227 * exceptions are thrown from this method. </p>
229 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
230 * @param server The server to wait on
231 * @param desiredStates A variable list of desired states, any one of which is allowed.
232 * @throws RequestFailedException If the request times out or fails for some reason
234 @SuppressWarnings("nls")
235 protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
236 throws RequestFailedException {
237 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
238 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
239 Context context = server.getContext();
240 Provider provider = context.getProvider();
241 ComputeService service = context.getComputeService();
244 long endTime = System.currentTimeMillis() + (timeout * 1000); //
246 while (rc.attempt()) {
249 server.waitForStateChange(pollInterval, timeout, desiredStates);
251 } catch (TimeoutException e) {
252 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
253 List<String> list = new ArrayList<>();
254 for (Server.Status desiredState : desiredStates) {
255 list.add(desiredState.name());
257 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
258 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
259 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
260 Integer.toString(rc.getRetryLimit()));
261 logger.error(msg, e);
264 } catch (ZoneException e) {
265 List<String> list = new ArrayList<>();
266 for (Server.Status desiredState : desiredStates) {
267 list.add(desiredState.name());
269 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
270 "server", server.getName(), server.getId(), StringHelper.asList(list),
271 server.getStatus().name(), e.getMessage());
272 logger.error(reason);
273 logger.error(EELFResourceManager.format(e));
275 // Instead of failing we are going to wait and try again.
276 // Timeout is reduced by delay time
277 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
279 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
280 // throw new RequestFailedException(e, operation, reason,
285 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
287 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
293 * Stop the specified server and wait for it to stop
295 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
296 * @param server The server to be stopped
298 @SuppressWarnings("nls")
299 protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
300 logger.debug(Msg.STOP_SERVER, server.getId());
303 Context context = server.getContext();
304 Provider provider = context.getProvider();
305 ComputeService service = context.getComputeService();
306 while (rc.attempt()) {
310 } catch (ContextConnectionException e) {
311 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
312 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
313 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
314 Integer.toString(rc.getRetryLimit()));
315 logger.error(msg, e);
320 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
322 throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
325 waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
329 * Start the server and wait for it to enter a running state
331 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
332 * @param server The server to be started
334 @SuppressWarnings("nls")
335 protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
336 logger.debug(Msg.START_SERVER, server.getId());
338 Context context = server.getContext();
339 Provider provider = context.getProvider();
340 ComputeService service = context.getComputeService();
341 while (rc.attempt()) {
345 } catch (ContextConnectionException e) {
346 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
347 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
348 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
349 Integer.toString(rc.getRetryLimit()));
350 logger.error(msg, e);
355 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
357 throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
360 waitForStateChange(rc, server, Server.Status.RUNNING);
365 * Un-Pause a paused server and wait for it to enter a running state
367 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
368 * @param server The server to be un-paused
370 @SuppressWarnings("nls")
371 protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
372 logger.debug(Msg.UNPAUSE_SERVER, server.getId());
375 Context context = server.getContext();
376 Provider provider = context.getProvider();
377 ComputeService service = context.getComputeService();
378 while (rc.attempt()) {
382 } catch (ContextConnectionException e) {
383 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
384 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
385 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
386 Integer.toString(rc.getRetryLimit()));
387 logger.error(msg, e);
392 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
394 throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
397 waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
402 * Generates the event indicating what happened
404 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
405 * @param success True if the event represents a successful outcome
406 * @param msg The detailed message
408 protected void generateEvent(@SuppressWarnings("unused") RequestContext rc,
409 @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
410 // indication to the DG to generate the event?
414 * Checks if the VM is connected to the Virtual Network and reachable
416 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
417 * @param server The server object representing the server we want to operate on
418 * @param context The interface cloud service provider to access services or the object model, or both
420 protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
421 throws ZoneException, RequestFailedException {
423 logger.info("Performing the VM Server networking status checks...");
424 List<Port> ports = server.getPorts();
426 NetworkService netSvc = context.getNetworkService();
429 for (Port port : ports) {
430 switch (port.getPortState().toString().toUpperCase()) {
432 /* The port is connected, configured, and usable for communication */
433 Network network = netSvc.getNetworkById(port.getNetwork());
434 validateNetwork(rc, server, port, network);
437 /* The port is disconnected or powered-off and cannot be used for communication */
438 msg = createErrorMessage(rc, server, port);
439 throw new RequestFailedException("VM Server Port status is OFFLINE", msg,
440 HttpStatus.PRECONDITION_FAILED_412, server);
442 /* The port's status is changing because of some event or operation. The final state is yet to be determined. */
443 msg = createErrorMessage(rc, server, port);
444 throw new RequestFailedException("VM Server Port status is PENDING", msg,
445 HttpStatus.PRECONDITION_FAILED_412, server);
447 /* The port is in an unknown state and cannot be used. */
448 msg = createErrorMessage(rc, server, port);
449 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg,
450 HttpStatus.PRECONDITION_FAILED_412, server);
452 logger.error("Invalid port state");
457 logger.info("Passed the VM Server the Hypervisor status checks..");
460 private String createErrorMessage(RequestContext rc, Server server, Port port) {
462 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
464 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
468 private void validateNetwork(RequestContext rc, Server server, Port port, Network network)
469 throws RequestFailedException {
471 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
472 msg = createErrorMessage(rc, server, port);
473 throw new RequestFailedException("VM Server Network is DOWN", msg,
474 HttpStatus.PRECONDITION_FAILED_412, server);
479 * Checks if the VM is connected to the Virtual Network and reachable
481 * @param server The server object representing the server we want to operate on
483 protected void checkHypervisor(Server server) throws ZoneException, RequestFailedException {
485 logger.info("Performing the Hypervisor status checks..");
488 if (server.getHypervisor() != null && server.getHypervisor().getStatus() != null
489 && server.getHypervisor().getState() != null) {
493 status = server.getHypervisor().getStatus().toString();
494 state = server.getHypervisor().getState().toString();
496 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
497 msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(),
500 throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg,
501 HttpStatus.PRECONDITION_FAILED_412, server);
504 msg = EELFResourceManager.format(Msg.HYPERVISOR_STATUS_UKNOWN, server.getName());
507 throw new RequestFailedException("Unable to determine Hypervisor status", msg,
508 HttpStatus.PRECONDITION_FAILED_412, server);
510 logger.info("Passed the Hypervisor status checks..");