2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 
   6  * Copyright (C) 2017 Amdocs
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  19  * ============LICENSE_END=========================================================
 
  20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
 
  23 package org.openecomp.appc.adapter.iaas.provider.operation.impl.base;
 
  25 import org.openecomp.appc.Constants;
 
  26 import org.openecomp.appc.adapter.iaas.impl.*;
 
  27 import org.openecomp.appc.i18n.Msg;
 
  28 import com.att.cdp.exceptions.ContextConnectionException;
 
  29 import com.att.cdp.exceptions.NotLoggedInException;
 
  30 import com.att.cdp.exceptions.TimeoutException;
 
  31 import com.att.cdp.exceptions.ZoneException;
 
  32 import com.att.cdp.pal.util.StringHelper;
 
  33 import com.att.cdp.zones.ComputeService;
 
  34 import com.att.cdp.zones.Context;
 
  35 import com.att.cdp.zones.ImageService;
 
  36 import com.att.cdp.zones.NetworkService;
 
  37 import com.att.cdp.zones.Provider;
 
  38 import com.att.cdp.zones.model.Hypervisor;
 
  39 import com.att.cdp.zones.model.Image;
 
  40 import com.att.cdp.zones.model.Network;
 
  41 import com.att.cdp.zones.model.Port;
 
  42 import com.att.cdp.zones.model.Server;
 
  43 import com.att.eelf.configuration.EELFLogger;
 
  44 import com.att.eelf.configuration.EELFManager;
 
  45 import com.att.eelf.i18n.EELFResourceManager;
 
  46 import org.glassfish.grizzly.http.util.HttpStatus;
 
  47 import java.util.ArrayList;
 
  48 import java.util.List;
 
  51  * @since September 29, 2016
 
  53 public abstract class ProviderServerOperation extends ProviderOperation{
 
  55     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class);
 
  58      * Looks up the indicated server using the provided context and returns the server to the caller
 
  63      *            The provider context
 
  65      *            The id of the server
 
  66      * @return The server, or null if there is a problem
 
  67      * @throws ZoneException
 
  68      *             If the server cannot be found
 
  69      * @throws RequestFailedException
 
  70      *             If the server cannot be found because we cant connect to the provider
 
  72     @SuppressWarnings("nls")
 
  73     protected Server lookupServer(RequestContext rc, Context context, String id)
 
  74             throws ZoneException, RequestFailedException {
 
  75         ComputeService service = context.getComputeService();
 
  78         Provider provider = context.getProvider();
 
  80         while (rc.attempt()) {
 
  82                 server = service.getServer(id);
 
  84             } catch (ContextConnectionException e) {
 
  85                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
  86                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
  87                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
  88                         Integer.toString(rc.getRetryLimit()));
 
  94             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
  96             doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
 
  97             throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 105      * Resume a suspended server and wait for it to enter a running state
 
 108      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 110      *            The server to be resumed
 
 111      * @throws ZoneException
 
 112      * @throws RequestFailedException
 
 114     @SuppressWarnings("nls")
 
 115     protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
 
 116         logger.debug(Msg.RESUME_SERVER, server.getId());
 
 118         Context context = server.getContext();
 
 120         Provider provider = context.getProvider();
 
 121         ComputeService service = context.getComputeService();
 
 122         while (rc.attempt()) {
 
 126             } catch (ContextConnectionException e) {
 
 127                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 128                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 129                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 130                         Integer.toString(rc.getRetryLimit()));
 
 131                 logger.error(msg, e);
 
 136             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 138             throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 141         waitForStateChange(rc, server, Server.Status.RUNNING);
 
 145     protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
 
 146         logger.info("Checking permissions for image service.");
 
 148             ImageService service = context.getImageService();
 
 149             service.getImageByName("CHECK_IMAGE_ACCESS");
 
 150             logger.info("Image service is accessible.");
 
 152         } catch (ZoneException e) {
 
 153             logger.warn("Image service could not be accessed. Some operations may fail.", e);
 
 160      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
 
 162      * This method checks the state of the server periodically for one of the desired states. When the server enters one
 
 163      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
 
 164      * desired states within the allocated timeout period, then the method returns a failed response (false). No
 
 165      * exceptions are thrown from this method.
 
 169      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 171      *            The server to wait on
 
 172      * @param desiredStates
 
 173      *            A variable list of desired states, any one of which is allowed.
 
 174      * @throws RequestFailedException
 
 175      *             If the request times out or fails for some reason
 
 176      * @throws NotLoggedInException
 
 178     @SuppressWarnings("nls")
 
 179     protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
 
 180             throws RequestFailedException, NotLoggedInException {
 
 181         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
 
 182         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
 
 183         Context context = image.getContext();
 
 184         Provider provider = context.getProvider();
 
 185         ImageService service = context.getImageService();
 
 188         long endTime = System.currentTimeMillis() + (timeout * 1000); //
 
 190         while (rc.attempt()) {
 
 193                     image.waitForStateChange(pollInterval, timeout, desiredStates);
 
 195                 } catch (TimeoutException e) {
 
 196                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
 
 197                     List<String> list = new ArrayList<>();
 
 198                     for (Image.Status desiredState : desiredStates) {
 
 199                         list.add(desiredState.name());
 
 201                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 202                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 203                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 204                             Integer.toString(rc.getRetryLimit()));
 
 205                     logger.error(msg, e);
 
 208             } catch (ZoneException e) {
 
 209                 List<String> list = new ArrayList<>();
 
 210                 for (Image.Status desiredState : desiredStates) {
 
 211                     list.add(desiredState.name());
 
 213                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
 
 214                         "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
 
 216                 logger.error(reason);
 
 217                 logger.error(EELFResourceManager.format(e));
 
 219                 // Instead of failing we are going to wait and try again.
 
 220                 // Timeout is reduced by delay time
 
 221                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
 
 223                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
 
 224                 // throw new RequestFailedException(e, operation, reason,
 
 225                 // HttpStatus.BAD_GATEWAY_502, server);
 
 230             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 232             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
 
 239      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
 
 241      * This method checks the state of the server periodically for one of the desired states. When the server enters one
 
 242      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
 
 243      * desired states within the allocated timeout period, then the method returns a failed response (false). No
 
 244      * exceptions are thrown from this method.
 
 248      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 250      *            The server to wait on
 
 251      * @param desiredStates
 
 252      *            A variable list of desired states, any one of which is allowed.
 
 253      * @throws RequestFailedException
 
 254      *             If the request times out or fails for some reason
 
 256     @SuppressWarnings("nls")
 
 257     protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
 
 258             throws RequestFailedException {
 
 259         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
 
 260         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
 
 261         Context context = server.getContext();
 
 262         Provider provider = context.getProvider();
 
 263         ComputeService service = context.getComputeService();
 
 266         long endTime = System.currentTimeMillis() + (timeout * 1000); //
 
 268         while (rc.attempt()) {
 
 271                     server.waitForStateChange(pollInterval, timeout, desiredStates);
 
 273                 } catch (TimeoutException e) {
 
 274                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
 
 275                     List<String> list = new ArrayList<>();
 
 276                     for (Server.Status desiredState : desiredStates) {
 
 277                         list.add(desiredState.name());
 
 279                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 280                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 281                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 282                             Integer.toString(rc.getRetryLimit()));
 
 283                     logger.error(msg, e);
 
 286             } catch (ZoneException e) {
 
 287                 List<String> list = new ArrayList<>();
 
 288                 for (Server.Status desiredState : desiredStates) {
 
 289                     list.add(desiredState.name());
 
 291                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
 
 292                         "server", server.getName(), server.getId(), StringHelper.asList(list), server.getStatus().name(),
 
 294                 logger.error(reason);
 
 295                 logger.error(EELFResourceManager.format(e));
 
 297                 // Instead of failing we are going to wait and try again.
 
 298                 // Timeout is reduced by delay time
 
 299                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
 
 301                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
 
 302                 // throw new RequestFailedException(e, operation, reason,
 
 303                 // HttpStatus.BAD_GATEWAY_502, server);
 
 308             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 310             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 316      * Stop the specified server and wait for it to stop
 
 319      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 321      *            The server to be stopped
 
 322      * @throws ZoneException
 
 323      * @throws RequestFailedException
 
 325     @SuppressWarnings("nls")
 
 326     protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
 
 327         logger.debug(Msg.STOP_SERVER, server.getId());
 
 330         Context context = server.getContext();
 
 331         Provider provider = context.getProvider();
 
 332         ComputeService service = context.getComputeService();
 
 333         while (rc.attempt()) {
 
 337             } catch (ContextConnectionException e) {
 
 338                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 339                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 340                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 341                         Integer.toString(rc.getRetryLimit()));
 
 342                 logger.error(msg, e);
 
 347             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 349             throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 352         waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
 
 356      * Start the server and wait for it to enter a running state
 
 359      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 361      *            The server to be started
 
 362      * @throws ZoneException
 
 363      * @throws RequestFailedException
 
 365     @SuppressWarnings("nls")
 
 366     protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
 
 367         logger.debug(Msg.START_SERVER, server.getId());
 
 369         Context context = server.getContext();
 
 370         Provider provider = context.getProvider();
 
 371         ComputeService service = context.getComputeService();
 
 372         while (rc.attempt()) {
 
 376             } catch (ContextConnectionException e) {
 
 377                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 378                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 379                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 380                         Integer.toString(rc.getRetryLimit()));
 
 381                 logger.error(msg, e);
 
 386             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 388             throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 391         waitForStateChange(rc, server, Server.Status.RUNNING);
 
 396      * Un-Pause a paused server and wait for it to enter a running state
 
 399      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 401      *            The server to be un-paused
 
 402      * @throws ZoneException
 
 403      * @throws RequestFailedException
 
 405     @SuppressWarnings("nls")
 
 406     protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
 
 407         logger.debug(Msg.UNPAUSE_SERVER, server.getId());
 
 410         Context context = server.getContext();
 
 411         Provider provider = context.getProvider();
 
 412         ComputeService service = context.getComputeService();
 
 413         while (rc.attempt()) {
 
 417             } catch (ContextConnectionException e) {
 
 418                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
 
 419                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
 
 420                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
 
 421                         Integer.toString(rc.getRetryLimit()));
 
 422                 logger.error(msg, e);
 
 427             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
 
 429             throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
 
 432         waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
 
 437      * Generates the event indicating what happened
 
 440      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 442      *            True if the event represents a successful outcome
 
 444      *            The detailed message
 
 446     protected void generateEvent(@SuppressWarnings("unused") RequestContext rc, @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
 
 447         // indication to the DG to generate the event?
 
 451      * Checks if the VM is connected to the Virtual Network and reachable
 
 454      *            The request context that manages the state and recovery of the request for the life of its processing.
 
 456      *             The server object representing the server we want to operate on
 
 458      *            The interface cloud service provider to access services or the object model, or both
 
 461         protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
 
 462                         throws ZoneException, RequestFailedException {
 
 464                 logger.info("Performing the VM Server networking status checks...");
 
 465                 List<Port> ports = server.getPorts();
 
 467                 NetworkService netSvc = context.getNetworkService();
 
 470                 for (Port port : ports) {
 
 472                         switch (port.getPortState().toString().toUpperCase()) {
 
 474                          * The port is connected, configured, and usable for communication
 
 477                                 Network network = netSvc.getNetworkById(port.getNetwork());
 
 478                                 // Subnet subnet = netSvc.getSubnetById(port.getSubnetId());
 
 479                                 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
 
 480                                         msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
 
 482                                         doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
 
 483                                         throw new RequestFailedException("VM Server Network is DOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
 
 489                          * The port is disconnected or powered-off and cannot be used for
 
 493                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
 
 495                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
 
 496                                 throw new RequestFailedException("VM Server Port status is OFFLINE", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
 
 500                          * The port's status is changing because of some event or operation.
 
 501                          * The final state is yet to be determined.
 
 504                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
 
 506                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
 
 507                                 throw new RequestFailedException("VM Server Port status is PENDING", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
 
 511                          * The port is in an unknown state and cannot be used.
 
 514                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
 
 516                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
 
 517                                 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
 
 522                 logger.info("Passed the VM Server the Hypervisor status checks..");
 
 527      * Checks if the VM is connected to the Virtual Network and reachable
 
 530      *             The server object representing the server we want to operate on
 
 532         protected void checkHypervisor(Server server)
 
 533                         throws ZoneException, RequestFailedException {
 
 535                 logger.info("Performing the Hypervisor status checks..");
 
 536                 String status = null, state = null, msg = null;
 
 538                 status = server.getHypervisor().getStatus().toString();
 
 539                 state = server.getHypervisor().getState().toString();
 
 541                 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
 
 542                         msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(), server.getName());
 
 543                         logger.error(msg.toString());
 
 545                         //doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
 
 546                         throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
 
 551                 logger.info("Passed the Hypervisor status checks..");
 
 556      * Checks if a Host machine is reachable
 
 559      *            IP Address of the Host Machine.
 
 561      *             The server object representing the Virtual Machine server
 
 565         /*private boolean isHostReachable(String ipAddress) throws IOException {
 
 567                 InetAddress address = InetAddress.getByName(ipAddress);
 
 569                 return address.isReachable(15000);