Applying license changes to all files
[appc.git] / appc-adapters / appc-iaas-adapter / appc-iaas-adapter-bundle / src / main / java / org / openecomp / appc / adapter / iaas / provider / operation / impl / base / ProviderServerOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
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
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
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.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.openecomp.appc.adapter.iaas.provider.operation.impl.base;
26
27 import org.openecomp.appc.Constants;
28 import org.openecomp.appc.adapter.iaas.impl.*;
29 import org.openecomp.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;
51
52 /**
53  * @since September 29, 2016
54  */
55 public abstract class ProviderServerOperation extends ProviderOperation{
56
57     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class);
58
59     /**
60      * Looks up the indicated server using the provided context and returns the server to the caller
61      *
62      * @param rc
63      *            The request context
64      * @param context
65      *            The provider context
66      * @param id
67      *            The id of the server
68      * @return The server, or null if there is a problem
69      * @throws ZoneException
70      *             If the server cannot be found
71      * @throws RequestFailedException
72      *             If the server cannot be found because we cant connect to the provider
73      */
74     @SuppressWarnings("nls")
75     protected Server lookupServer(RequestContext rc, Context context, String id)
76             throws ZoneException, RequestFailedException {
77         ComputeService service = context.getComputeService();
78         Server server = null;
79         String msg;
80         Provider provider = context.getProvider();
81
82         while (rc.attempt()) {
83             try {
84                 server = service.getServer(id);
85                 break;
86             } catch (ContextConnectionException e) {
87                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
88                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
89                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
90                         Integer.toString(rc.getRetryLimit()));
91                 logger.error(msg, e);
92                 rc.delay();
93             }
94         }
95         if (rc.isFailed()) {
96             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
97             logger.error(msg);
98             doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
99             throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server);
100         }
101         return server;
102     }
103
104
105
106     /**
107      * Resume a suspended server and wait for it to enter a running state
108      *
109      * @param rc
110      *            The request context that manages the state and recovery of the request for the life of its processing.
111      * @param server
112      *            The server to be resumed
113      * @throws ZoneException
114      * @throws RequestFailedException
115      */
116     @SuppressWarnings("nls")
117     protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
118         logger.debug(Msg.RESUME_SERVER, server.getId());
119
120         Context context = server.getContext();
121         String msg;
122         Provider provider = context.getProvider();
123         ComputeService service = context.getComputeService();
124         while (rc.attempt()) {
125             try {
126                 server.resume();
127                 break;
128             } catch (ContextConnectionException e) {
129                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
130                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
131                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
132                         Integer.toString(rc.getRetryLimit()));
133                 logger.error(msg, e);
134                 rc.delay();
135             }
136         }
137         if (rc.isFailed()) {
138             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
139             logger.error(msg);
140             throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
141         }
142         rc.reset();
143         waitForStateChange(rc, server, Server.Status.RUNNING);
144     }
145
146
147     protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
148         logger.info("Checking permissions for image service.");
149         try {
150             ImageService service = context.getImageService();
151             service.getImageByName("CHECK_IMAGE_ACCESS");
152             logger.info("Image service is accessible.");
153             return true;
154         } catch (ZoneException e) {
155             logger.warn("Image service could not be accessed. Some operations may fail.", e);
156             return false;
157         }
158     }
159
160
161     /**
162      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
163      * <p>
164      * This method checks the state of the server periodically for one of the desired states. When the server enters one
165      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
166      * desired states within the allocated timeout period, then the method returns a failed response (false). No
167      * exceptions are thrown from this method.
168      * </p>
169      *
170      * @param rc
171      *            The request context that manages the state and recovery of the request for the life of its processing.
172      * @param image
173      *            The server to wait on
174      * @param desiredStates
175      *            A variable list of desired states, any one of which is allowed.
176      * @throws RequestFailedException
177      *             If the request times out or fails for some reason
178      * @throws NotLoggedInException
179      */
180     @SuppressWarnings("nls")
181     protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
182             throws RequestFailedException, NotLoggedInException {
183         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
184         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
185         Context context = image.getContext();
186         Provider provider = context.getProvider();
187         ImageService service = context.getImageService();
188         String msg;
189
190         long endTime = System.currentTimeMillis() + (timeout * 1000); //
191
192         while (rc.attempt()) {
193             try {
194                 try {
195                     image.waitForStateChange(pollInterval, timeout, desiredStates);
196                     break;
197                 } catch (TimeoutException e) {
198                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
199                     List<String> list = new ArrayList<>();
200                     for (Image.Status desiredState : desiredStates) {
201                         list.add(desiredState.name());
202                     }
203                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
204                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
205                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
206                             Integer.toString(rc.getRetryLimit()));
207                     logger.error(msg, e);
208                     rc.delay();
209                 }
210             } catch (ZoneException e) {
211                 List<String> list = new ArrayList<>();
212                 for (Image.Status desiredState : desiredStates) {
213                     list.add(desiredState.name());
214                 }
215                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
216                         "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
217                         e.getMessage());
218                 logger.error(reason);
219                 logger.error(EELFResourceManager.format(e));
220
221                 // Instead of failing we are going to wait and try again.
222                 // Timeout is reduced by delay time
223                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
224                 rc.delay();
225                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
226                 // throw new RequestFailedException(e, operation, reason,
227                 // HttpStatus.BAD_GATEWAY_502, server);
228             }
229         }
230
231         if (rc.isFailed()) {
232             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
233             logger.error(msg);
234             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
235         }
236         rc.reset();
237     }
238
239
240     /**
241      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
242      * <p>
243      * This method checks the state of the server periodically for one of the desired states. When the server enters one
244      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
245      * desired states within the allocated timeout period, then the method returns a failed response (false). No
246      * exceptions are thrown from this method.
247      * </p>
248      *
249      * @param rc
250      *            The request context that manages the state and recovery of the request for the life of its processing.
251      * @param server
252      *            The server to wait on
253      * @param desiredStates
254      *            A variable list of desired states, any one of which is allowed.
255      * @throws RequestFailedException
256      *             If the request times out or fails for some reason
257      */
258     @SuppressWarnings("nls")
259     protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
260             throws RequestFailedException {
261         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
262         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
263         Context context = server.getContext();
264         Provider provider = context.getProvider();
265         ComputeService service = context.getComputeService();
266         String msg;
267
268         long endTime = System.currentTimeMillis() + (timeout * 1000); //
269
270         while (rc.attempt()) {
271             try {
272                 try {
273                     server.waitForStateChange(pollInterval, timeout, desiredStates);
274                     break;
275                 } catch (TimeoutException e) {
276                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
277                     List<String> list = new ArrayList<>();
278                     for (Server.Status desiredState : desiredStates) {
279                         list.add(desiredState.name());
280                     }
281                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
282                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
283                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
284                             Integer.toString(rc.getRetryLimit()));
285                     logger.error(msg, e);
286                     rc.delay();
287                 }
288             } catch (ZoneException e) {
289                 List<String> list = new ArrayList<>();
290                 for (Server.Status desiredState : desiredStates) {
291                     list.add(desiredState.name());
292                 }
293                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
294                         "server", server.getName(), server.getId(), StringHelper.asList(list), server.getStatus().name(),
295                         e.getMessage());
296                 logger.error(reason);
297                 logger.error(EELFResourceManager.format(e));
298
299                 // Instead of failing we are going to wait and try again.
300                 // Timeout is reduced by delay time
301                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
302                 rc.delay();
303                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
304                 // throw new RequestFailedException(e, operation, reason,
305                 // HttpStatus.BAD_GATEWAY_502, server);
306             }
307         }
308
309         if (rc.isFailed()) {
310             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
311             logger.error(msg);
312             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
313         }
314         rc.reset();
315     }
316
317     /**
318      * Stop the specified server and wait for it to stop
319      *
320      * @param rc
321      *            The request context that manages the state and recovery of the request for the life of its processing.
322      * @param server
323      *            The server to be stopped
324      * @throws ZoneException
325      * @throws RequestFailedException
326      */
327     @SuppressWarnings("nls")
328     protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
329         logger.debug(Msg.STOP_SERVER, server.getId());
330
331         String msg;
332         Context context = server.getContext();
333         Provider provider = context.getProvider();
334         ComputeService service = context.getComputeService();
335         while (rc.attempt()) {
336             try {
337                 server.stop();
338                 break;
339             } catch (ContextConnectionException e) {
340                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
341                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
342                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
343                         Integer.toString(rc.getRetryLimit()));
344                 logger.error(msg, e);
345                 rc.delay();
346             }
347         }
348         if (rc.isFailed()) {
349             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
350             logger.error(msg);
351             throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
352         }
353         rc.reset();
354         waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
355     }
356
357     /**
358      * Start the server and wait for it to enter a running state
359      *
360      * @param rc
361      *            The request context that manages the state and recovery of the request for the life of its processing.
362      * @param server
363      *            The server to be started
364      * @throws ZoneException
365      * @throws RequestFailedException
366      */
367     @SuppressWarnings("nls")
368     protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
369         logger.debug(Msg.START_SERVER, server.getId());
370         String msg;
371         Context context = server.getContext();
372         Provider provider = context.getProvider();
373         ComputeService service = context.getComputeService();
374         while (rc.attempt()) {
375             try {
376                 server.start();
377                 break;
378             } catch (ContextConnectionException e) {
379                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
380                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
381                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
382                         Integer.toString(rc.getRetryLimit()));
383                 logger.error(msg, e);
384                 rc.delay();
385             }
386         }
387         if (rc.isFailed()) {
388             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
389             logger.error(msg);
390             throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
391         }
392         rc.reset();
393         waitForStateChange(rc, server, Server.Status.RUNNING);
394     }
395
396
397     /**
398      * Un-Pause a paused server and wait for it to enter a running state
399      *
400      * @param rc
401      *            The request context that manages the state and recovery of the request for the life of its processing.
402      * @param server
403      *            The server to be un-paused
404      * @throws ZoneException
405      * @throws RequestFailedException
406      */
407     @SuppressWarnings("nls")
408     protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
409         logger.debug(Msg.UNPAUSE_SERVER, server.getId());
410
411         String msg;
412         Context context = server.getContext();
413         Provider provider = context.getProvider();
414         ComputeService service = context.getComputeService();
415         while (rc.attempt()) {
416             try {
417                 server.unpause();
418                 break;
419             } catch (ContextConnectionException e) {
420                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
421                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
422                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
423                         Integer.toString(rc.getRetryLimit()));
424                 logger.error(msg, e);
425                 rc.delay();
426             }
427         }
428         if (rc.isFailed()) {
429             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
430             logger.error(msg);
431             throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
432         }
433         rc.reset();
434         waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
435     }
436
437
438     /**
439      * Generates the event indicating what happened
440      *
441      * @param rc
442      *            The request context that manages the state and recovery of the request for the life of its processing.
443      * @param success
444      *            True if the event represents a successful outcome
445      * @param msg
446      *            The detailed message
447      */
448     protected void generateEvent(@SuppressWarnings("unused") RequestContext rc, @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
449         // indication to the DG to generate the event?
450     }
451     
452     /**
453      * Checks if the VM is connected to the Virtual Network and reachable
454      *
455      * @param rc
456      *            The request context that manages the state and recovery of the request for the life of its processing.
457      * @param server
458      *             The server object representing the server we want to operate on
459      * @param context
460      *            The interface cloud service provider to access services or the object model, or both
461
462      */
463         protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
464                         throws ZoneException, RequestFailedException {
465
466                 logger.info("Performing the VM Server networking status checks...");
467                 List<Port> ports = server.getPorts();
468
469                 NetworkService netSvc = context.getNetworkService();
470
471                 String msg;
472                 for (Port port : ports) {
473
474                         switch (port.getPortState().toString().toUpperCase()) {
475                         /**
476                          * The port is connected, configured, and usable for communication
477                          */
478                         case "ONLINE":
479                                 Network network = netSvc.getNetworkById(port.getNetwork());
480                                 // Subnet subnet = netSvc.getSubnetById(port.getSubnetId());
481                                 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
482                                         msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
483                                         logger.error(msg);
484                                         doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
485                                         throw new RequestFailedException("VM Server Network is DOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
486                                                         server);
487                                 }
488                                 break;
489
490                         /**
491                          * The port is disconnected or powered-off and cannot be used for
492                          * communication
493                          */
494                         case "OFFLINE":
495                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
496                                 logger.error(msg);
497                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
498                                 throw new RequestFailedException("VM Server Port status is OFFLINE", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
499                                                 server);
500
501                         /**
502                          * The port's status is changing because of some event or operation.
503                          * The final state is yet to be determined.
504                          */
505                         case "PENDING":
506                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
507                                 logger.error(msg);
508                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
509                                 throw new RequestFailedException("VM Server Port status is PENDING", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
510                                                 server);
511
512                         /**
513                          * The port is in an unknown state and cannot be used.
514                          */
515                         case "UNKNOWN":
516                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
517                                 logger.error(msg);
518                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
519                                 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
520                                                 server);
521                         }
522
523                 }
524                 logger.info("Passed the VM Server the Hypervisor status checks..");
525
526         }
527     
528         /**
529      * Checks if the VM is connected to the Virtual Network and reachable
530      *
531      * @param server
532      *             The server object representing the server we want to operate on
533      */
534         protected void checkHypervisor(Server server)
535                         throws ZoneException, RequestFailedException {
536
537                 logger.info("Performing the Hypervisor status checks..");
538                 String status = null, state = null, msg = null;
539
540                 status = server.getHypervisor().getStatus().toString();
541                 state = server.getHypervisor().getState().toString();
542                 
543                 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
544                         msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(), server.getName());
545                         logger.error(msg.toString());
546                 
547                         //doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
548                         throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
549                                         server);
550
551                 }
552                 
553                 logger.info("Passed the Hypervisor status checks..");
554                 
555         }
556
557         /**
558      * Checks if a Host machine is reachable
559      *
560      * @param ipAddress
561      *            IP Address of the Host Machine.
562      * @param server
563      *             The server object representing the Virtual Machine server
564      * @return boolean
565      *            
566      */
567         /*private boolean isHostReachable(String ipAddress) throws IOException {
568                 
569                 InetAddress address = InetAddress.getByName(ipAddress);
570                 
571                 return address.isReachable(15000); 
572                 
573
574         }*/
575     
576 }