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 org.onap.appc.Constants;
28 import org.onap.appc.adapter.iaas.impl.*;
29 import org.onap.appc.i18n.Msg;
30 import com.att.cdp.exceptions.ContextConnectionException;
31 import com.att.cdp.exceptions.NotLoggedInException;
32 import com.att.cdp.exceptions.TimeoutException;
33 import com.att.cdp.exceptions.ZoneException;
34 import com.att.cdp.pal.util.StringHelper;
35 import com.att.cdp.zones.ComputeService;
36 import com.att.cdp.zones.Context;
37 import com.att.cdp.zones.ImageService;
38 import com.att.cdp.zones.NetworkService;
39 import com.att.cdp.zones.Provider;
40 import com.att.cdp.zones.model.Hypervisor;
41 import com.att.cdp.zones.model.Image;
42 import com.att.cdp.zones.model.Network;
43 import com.att.cdp.zones.model.Port;
44 import com.att.cdp.zones.model.Server;
45 import com.att.eelf.configuration.EELFLogger;
46 import com.att.eelf.configuration.EELFManager;
47 import com.att.eelf.i18n.EELFResourceManager;
48 import org.glassfish.grizzly.http.util.HttpStatus;
49 import java.util.ArrayList;
50 import java.util.List;
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);
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
106 * @throws ZoneException
107 * @throws RequestFailedException
109 @SuppressWarnings("nls")
110 protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
111 logger.debug(Msg.RESUME_SERVER, server.getId());
113 Context context = server.getContext();
115 Provider provider = context.getProvider();
116 ComputeService service = context.getComputeService();
117 while (rc.attempt()) {
121 } catch (ContextConnectionException e) {
122 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
123 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
124 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
125 Integer.toString(rc.getRetryLimit()));
126 logger.error(msg, e);
131 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
133 throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
136 waitForStateChange(rc, server, Server.Status.RUNNING);
140 protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
141 logger.info("Checking permissions for image service.");
143 ImageService service = context.getImageService();
144 service.getImageByName("CHECK_IMAGE_ACCESS");
145 logger.info("Image service is accessible.");
147 } catch (ZoneException e) {
148 logger.warn("Image service could not be accessed. Some operations may fail.", e);
155 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
157 * This method checks the state of the server periodically for one of the desired states. When the server enters one
158 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
159 * desired states within the allocated timeout period, then the method returns a failed response (false). No
160 * exceptions are thrown from this method.
163 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
164 * @param image The server to wait on
165 * @param desiredStates A variable list of desired states, any one of which is allowed.
166 * @throws RequestFailedException If the request times out or fails for some reason
167 * @throws NotLoggedInException
169 @SuppressWarnings("nls")
170 protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
171 throws RequestFailedException, NotLoggedInException {
172 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
173 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
174 Context context = image.getContext();
175 Provider provider = context.getProvider();
176 ImageService service = context.getImageService();
179 long endTime = System.currentTimeMillis() + (timeout * 1000); //
181 while (rc.attempt()) {
184 image.waitForStateChange(pollInterval, timeout, desiredStates);
186 } catch (TimeoutException e) {
187 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
188 List<String> list = new ArrayList<>();
189 for (Image.Status desiredState : desiredStates) {
190 list.add(desiredState.name());
192 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
193 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
194 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
195 Integer.toString(rc.getRetryLimit()));
196 logger.error(msg, e);
199 } catch (ZoneException e) {
200 List<String> list = new ArrayList<>();
201 for (Image.Status desiredState : desiredStates) {
202 list.add(desiredState.name());
204 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
205 "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
207 logger.error(reason);
208 logger.error(EELFResourceManager.format(e));
210 // Instead of failing we are going to wait and try again.
211 // Timeout is reduced by delay time
212 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
214 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
215 // throw new RequestFailedException(e, operation, reason,
216 // HttpStatus.BAD_GATEWAY_502, server);
221 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
223 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
230 * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
232 * This method checks the state of the server periodically for one of the desired states. When the server enters one
233 * of the desired states, the method returns a successful indication (true). If the server never enters one of the
234 * desired states within the allocated timeout period, then the method returns a failed response (false). No
235 * exceptions are thrown from this method.
238 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
239 * @param server The server to wait on
240 * @param desiredStates A variable list of desired states, any one of which is allowed.
241 * @throws RequestFailedException If the request times out or fails for some reason
243 @SuppressWarnings("nls")
244 protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
245 throws RequestFailedException {
246 int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
247 int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
248 Context context = server.getContext();
249 Provider provider = context.getProvider();
250 ComputeService service = context.getComputeService();
253 long endTime = System.currentTimeMillis() + (timeout * 1000); //
255 while (rc.attempt()) {
258 server.waitForStateChange(pollInterval, timeout, desiredStates);
260 } catch (TimeoutException e) {
261 @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
262 List<String> list = new ArrayList<>();
263 for (Server.Status desiredState : desiredStates) {
264 list.add(desiredState.name());
266 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
267 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
268 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
269 Integer.toString(rc.getRetryLimit()));
270 logger.error(msg, e);
273 } catch (ZoneException e) {
274 List<String> list = new ArrayList<>();
275 for (Server.Status desiredState : desiredStates) {
276 list.add(desiredState.name());
278 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
279 "server", server.getName(), server.getId(), StringHelper.asList(list),
280 server.getStatus().name(), e.getMessage());
281 logger.error(reason);
282 logger.error(EELFResourceManager.format(e));
284 // Instead of failing we are going to wait and try again.
285 // Timeout is reduced by delay time
286 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
288 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
289 // throw new RequestFailedException(e, operation, reason,
290 // HttpStatus.BAD_GATEWAY_502, server);
295 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
297 throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
303 * Stop the specified server and wait for it to stop
305 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
306 * @param server The server to be stopped
307 * @throws ZoneException
308 * @throws RequestFailedException
310 @SuppressWarnings("nls")
311 protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
312 logger.debug(Msg.STOP_SERVER, server.getId());
315 Context context = server.getContext();
316 Provider provider = context.getProvider();
317 ComputeService service = context.getComputeService();
318 while (rc.attempt()) {
322 } catch (ContextConnectionException e) {
323 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
324 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
325 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
326 Integer.toString(rc.getRetryLimit()));
327 logger.error(msg, e);
332 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
334 throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
337 waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
341 * Start the server and wait for it to enter a running state
343 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
344 * @param server The server to be started
345 * @throws ZoneException
346 * @throws RequestFailedException
348 @SuppressWarnings("nls")
349 protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
350 logger.debug(Msg.START_SERVER, server.getId());
352 Context context = server.getContext();
353 Provider provider = context.getProvider();
354 ComputeService service = context.getComputeService();
355 while (rc.attempt()) {
359 } catch (ContextConnectionException e) {
360 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
361 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
362 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
363 Integer.toString(rc.getRetryLimit()));
364 logger.error(msg, e);
369 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
371 throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
374 waitForStateChange(rc, server, Server.Status.RUNNING);
379 * Un-Pause a paused server and wait for it to enter a running state
381 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
382 * @param server The server to be un-paused
383 * @throws ZoneException
384 * @throws RequestFailedException
386 @SuppressWarnings("nls")
387 protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
388 logger.debug(Msg.UNPAUSE_SERVER, server.getId());
391 Context context = server.getContext();
392 Provider provider = context.getProvider();
393 ComputeService service = context.getComputeService();
394 while (rc.attempt()) {
398 } catch (ContextConnectionException e) {
399 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
400 context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
401 Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
402 Integer.toString(rc.getRetryLimit()));
403 logger.error(msg, e);
408 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
410 throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
413 waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
418 * Generates the event indicating what happened
420 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
421 * @param success True if the event represents a successful outcome
422 * @param msg The detailed message
424 protected void generateEvent(@SuppressWarnings("unused") RequestContext rc,
425 @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
426 // indication to the DG to generate the event?
430 * Checks if the VM is connected to the Virtual Network and reachable
432 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
433 * @param server The server object representing the server we want to operate on
434 * @param context The interface cloud service provider to access services or the object model, or both
437 protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
438 throws ZoneException, RequestFailedException {
440 logger.info("Performing the VM Server networking status checks...");
441 List<Port> ports = server.getPorts();
443 NetworkService netSvc = context.getNetworkService();
446 for (Port port : ports) {
448 switch (port.getPortState().toString().toUpperCase()) {
450 * The port is connected, configured, and usable for communication
453 Network network = netSvc.getNetworkById(port.getNetwork());
454 // Subnet subnet = netSvc.getSubnetById(port.getSubnetId());
455 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
456 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
458 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
459 throw new RequestFailedException("VM Server Network is DOWN", msg.toString(),
460 HttpStatus.PRECONDITION_FAILED_412, server);
465 * The port is disconnected or powered-off and cannot be used for communication
468 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
470 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
471 throw new RequestFailedException("VM Server Port status is OFFLINE", msg.toString(),
472 HttpStatus.PRECONDITION_FAILED_412, server);
475 * The port's status is changing because of some event or operation. The final state is yet to be
479 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
481 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
482 throw new RequestFailedException("VM Server Port status is PENDING", msg.toString(),
483 HttpStatus.PRECONDITION_FAILED_412, server);
486 * The port is in an unknown state and cannot be used.
489 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
491 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
492 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg.toString(),
493 HttpStatus.PRECONDITION_FAILED_412, server);
497 logger.info("Passed the VM Server the Hypervisor status checks..");
502 * Checks if the VM is connected to the Virtual Network and reachable
504 * @param server The server object representing the server we want to operate on
506 protected void checkHypervisor(Server server) throws ZoneException, RequestFailedException {
508 logger.info("Performing the Hypervisor status checks..");
511 if (server.getHypervisor() != null && server.getHypervisor().getStatus() != null
512 && server.getHypervisor().getState() != null) {
513 String status = null;
516 status = server.getHypervisor().getStatus().toString();
517 state = server.getHypervisor().getState().toString();
519 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
520 msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(),
522 logger.error(msg.toString());
524 // doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
525 throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg.toString(),
526 HttpStatus.PRECONDITION_FAILED_412, server);
530 msg = EELFResourceManager.format(Msg.HYPERVISOR_STATUS_UKNOWN, server.getName());
531 logger.error(msg.toString());
533 throw new RequestFailedException("Unable to determine Hypervisor status", msg.toString(),
534 HttpStatus.PRECONDITION_FAILED_412, server);
537 logger.info("Passed the Hypervisor status checks..");
542 * Checks if a Host machine is reachable
544 * @param ipAddress IP Address of the Host Machine.
545 * @param server The server object representing the Virtual Machine server
550 * private boolean isHostReachable(String ipAddress) throws IOException {
552 * InetAddress address = InetAddress.getByName(ipAddress);
554 * return address.isReachable(15000);